⬆️ ⬇️

Creating an Android application or a project without a name

Prehistory



One fine day, I decided to start learning English, and immediately before studying I consulted a teacher who teaches this language, since I thought he would share his experience with me. As a result, we agreed with him that I should start my study with the words of the language, because basically I use my knowledge when I visit English-language websites, and only then take up grammar. He suggested a very interesting way of studying (at least for me). At one time, in order for words to be stored in memory, he would take an ordinary sheet of paper, lined it into equal rectangles on one side and cut a sheet, then write an English word on one side of the resulting rectangle, and an English word on the other, after that he would take a box, I put the resulting cards in there, mixed them up and extracted them one by one, looked at the word and pronounced the translation.

If you do this procedure every day for an hour or two and periodically, replenish your card index, then the words are remembered very well.



Since then, I have decided that I will always do this and in the near future I will start reading in English, as in my native language! But after a while, I began to tire of cutting cards and spending time on it, and by the same time I was absolutely not enough, at that moment I had a thought, why not create a program under the android OS (because my phone is with this system), which will perform a similar function!



From that moment a project was born that I did not come up with a name for.



purpose



The purpose of this project, initially, was to automate the addition of words to the card file and their further exploitation, but later a couple of ideas came to me and it was very interesting to develop the project, but after two weeks it became boring and I got bored, and completely throw it away, like all previous ones I did not want to, and so I decided to try myself as the author of this article and share the experience gained in the field of network programming and programming for android. In this article I will try, as far as possible, to consistently and step by step describe the entire procedure for creating this program.

')

Program



To begin with, I will describe in detail the product I created and review the functionality, then, who are interested in it, I can read further about the creation of this miracle.



Description



The first thing I would like to tell is about the menu, I tried to make it as attractive as possible, I always had "excellent" taste, so this is what came of it.



image



As you can see in the image, there is nothing special about it, but when you click on the button “Check words” or “Words”, a submenu appears, so to speak.



image



image



As can be seen from the images above, the buttons “In Alphabetical order”, “In reverse order” and “Random” have the same property. I marked all of them with a special symbol “+”, and when opened, the symbol is replaced with “-”. When you click on one of the items of the open menu again, it is rolled up to its original position.



Before taking a test or changing and deleting words, you need to add them, therefore now we will look at this particular mechanism, but before that you need to digress a little from this topic so that everything is clear in the future.



As I have already said, before creating a project, I was visited by many ideas and one of them, it is a simplification of adding words to the program. It is no secret that a person is lazy and not everyone will like to manually create their own card index, especially if you need to fill up as many as three fields (although the transcription is not necessary), in the age of Internet development and data transmission over long distances in one instant.



image



An idea occurred to me, why shouldn’t a program user share his card file with the whole world? Therefore, at the moment of adding a word to his personal dictionary, the user is unaware (if there is an internet connection) loads it on the server, where it is stored in the database and waits until another user adds it to himself, and so, by itself the mechanism of adding words is nothing complicated, simple and understandable even to a child.



The program also has the function of changing and deleting words. Here, everything is quite simple: after clicking on the desired menu item, activates in front of us, where the words are arranged in alphabetical order. The windows for deleting and modifying words are almost the same, just by the icon on the button with the word, so one xml file was used to create them.



image



image



If the user changes the word, then to change it, the xml-file of adding words is used, only with a different functionality, all three fields are filled with old values.



image



After entering new values, when you click on the corresponding button, the word is changed and stored on the user's device without making changes to the database on the server. Deleting words / words is also very simple, I can’t even imagine how to complicate this process.



image



image



As you can see from the images, you can delete all the words at once or you can delete each word one by one, but before each deletion a dialog box will pop up confirming the action.



Now, when I described one of the main functionals, namely the addition / deletion / modification of words, consider the most important test passing by these words, and then I will describe an alternative way to add words.



It could be noted in the figure above that the test can be passed in three different orders: alphabetical, inverse and random. The test object can be either the English version of the word, or Russian, or transcription.



image



As can be seen from the figure, the field with the English version of the word is active, which means this option is being tested. Depending on the selected test, only one input field is always active, the others are not subject to change. The line “Status” indicates whether the entered user’s version is correct, in order to find out, you must click on the “Check” button, it also shows how many words have been passed and their number, the “Next” button can not be viewed in detail, but I would like to Note that you could add a return button to the previous word. The test can be completed by reaching the last word or by the menu item.



image



After you have passed or completed the test, your result is presented to your attention.



image



Words that have been entered correctly are displayed in green, the rest are red, then you can either go to the main menu or take the test again.



Now consider an alternative way to add words, to use it, you need to go to the menu item "Download" and there you can view the words that have been added to the server in the manner described above.



image



The figure shows that this activation is almost the same as activating changes and deletions, except that there are CheckBoxes instead of Buttones.



I would like to note that the words from the server arrive in small portions, namely, one hundred pieces, after the user reaches the penultimate one, another hundred are loaded, and so on, until the server returns the last word. In order for the word / words to be added to your card file, you should use the menu items.



image



As you can see in the image, you can download highlighted words, or those words that are currently loaded. How many words will be saved is shown to the left of the menu item.



In the images above, you can see that the activation of changes / deletions / downloads of words is Edit - “Find”, since it is implemented the same everywhere, we consider only the example of the Downloads window.



Despite the simplicity of implementation, the search for words in this program is my favorite development (do not count the loading of words from the server). He is "live", looking for English and Russian words, and also simple and easy to use.



image



image



image



image



Also in the program there is a menu item "View words", where all the words are displayed in the HTML-table.



image



Finally, I would like to note that all the functionality of all activations is duplicated in the menu.



image



image



image



image



image



Implementation



As it was not difficult to guess, the program consists of two parts, it is a server and client application, so this item will be divided into two parts, and separately I will describe the implementation of each. I will consider only what I consider to be the most necessary, otherwise the article will be very cumbersome, especially since most of the program is nothing difficult.



Client part



I will begin to describe the client part in order, so the first thing we consider is the creation of the menu, to be more precise, the implementation of the folding / unfolding submenu. This fragment is very simple and requires almost no explanation, so I will describe only the logic of the code.



<Button android:id="@+id/alphabet" android:layout_width="@dimen/b_size" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/b_alphabet" android:visibility="gone" android:onClick="Alphabet"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <Button android:id="@+id/english1" android:layout_width="@dimen/b_size2" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/b_english" android:visibility="gone" android:onClick="TestingWords"/> <Button android:id="@+id/transcription1" android:layout_width="@dimen/b_size2" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/b_transcription" android:visibility="gone" android:onClick="TestingWords"/> <Button android:id="@+id/russian1" android:layout_width="@dimen/b_size2" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/b_russian" android:visibility="gone" android:onClick="TestingWords"/> </LinearLayout> 


As can be seen from the code snippet of the xml-file, initially all items of the submenu are hidden, then, when you press the corresponding button, they become visible, and other items that were active are minimized, one of the functions is shown below, the rest are almost the same.



 public void Alphabet(View view) { click_alphabet = !click_alphabet; if(Btn_Null()) Btn_Gone(); btn_english = (Button) findViewById(R.id.english1); btn_transcription = (Button) findViewById(R.id.transcription1); btn_russian = (Button) findViewById(R.id.russian1); if(click_alphabet) { btn_english.setVisibility(View.VISIBLE); btn_transcription.setVisibility(View.VISIBLE); btn_russian.setVisibility(View.VISIBLE); btn_alphabet.setText("   -"); } else { Btn_Gone(); btn_alphabet.setText("   +"); } } 


The variable click_alphabet - checks if there was a second press of a button, if "yes", then the submenu for which this item is responsible is minimized.



Function Btn_Null () - checks the initialization of all buttons.

The Btn_Gone () function collapses absolutely all menu items / sub-items.



Now consider adding a word to the database on the server and on the smartphone. All words that the user has added to himself are stored in the TreeMap <String, TransRus> class, the key word for this class is the English word, and transcription and translation are stored in the TransRus class.



 public class TransRus { private String transcription; private String russian; boolean error; TransRus() { transcription = new String(""); russian = new String(""); error = false; } void getTranscription(String tr) { transcription = tr; } void getRussian(String rs) { russian = rs; } String setTranscription() { return transcription; } String setRussian() { return russian; } void getError(boolean t) { error = t; } boolean setError() { return error; } } 


The TreeMap class is wrapped in a CollectionWords class; a comparator was also written for it, which ignores the case of letters.



 class ComparatorNotRegister implements Comparator<String> { public int compare(String str1, String str2) { return str1.compareToIgnoreCase(str2); } } public class CollectionWords { static TreeMap<String, TransRus> coll_words = null; static final String file1 = "english"; static final String file2 = "transcription"; static final String file3 = "russian"; static void InitializationCollWords() { if(coll_words != null) return; coll_words = new TreeMap<String, TransRus>(new ComparatorNotRegister()); } static void PutCollWords(String english, String transcription, String russian) { TransRus tr = new TransRus(); tr.getTranscription(transcription); tr.getRussian(russian); coll_words.put(english, tr); } static void ChangedWordEng(String old_english, String new_english, String transcription, String russian) { TransRus temp = coll_words.get(old_english); coll_words.remove(old_english); PutCollWords(new_english, transcription, russian); } static void DeleteWords(String eng) { coll_words.remove(eng); } static void WriteWords(AppCompatActivity t) { try( BufferedWriter eng = new BufferedWriter(new OutputStreamWriter(t.openFileOutput(file1, t.MODE_PRIVATE))); BufferedWriter trans = new BufferedWriter(new OutputStreamWriter(t.openFileOutput(file2, t.MODE_PRIVATE))); BufferedWriter rus = new BufferedWriter(new OutputStreamWriter(t.openFileOutput(file3, t.MODE_PRIVATE)))) { for(Map.Entry<String, TransRus> me : CollectionWords.AllWords()) { eng.write(me.getKey() + "\n"); trans.write(me.getValue().setTranscription() + "\n"); rus.write(me.getValue().setRussian() + "\n"); } } catch (FileNotFoundException e) { Log.d("MyLog", "WF: " + e); } catch (IOException e) { Log.d("MyLog", "WIOE: " + e); } catch(NullPointerException e) { Log.d("MyLog", "WN: " + e); } catch (Exception e) { Log.d("MyLog", "WE: " + e); } } static void ReadWords(AppCompatActivity t) { try( BufferedReader eng = new BufferedReader(new InputStreamReader(t.openFileInput(file1))); BufferedReader trans = new BufferedReader(new InputStreamReader(t.openFileInput(file2))); BufferedReader rus = new BufferedReader(new InputStreamReader(t.openFileInput(file3)))) { String str_eng; String str_trans; String str_rus; while(((str_eng = eng.readLine()) != null) && ((str_trans = trans.readLine()) != null) && ((str_rus = rus.readLine()) != null)) { CollectionWords.PutCollWords(str_eng, str_trans, str_rus); } Log.d("MyLog", "Hyi tam"); } catch (FileNotFoundException e) { Log.d("MyLog", "RF: " + e); } catch (IOException e) { Log.d("MyLog", "RIO: " + e); } catch(NullPointerException e) { Log.d("MyLog", "RN: " + e); } } static Set<Map.Entry<String, TransRus>> AllWords() { return coll_words.entrySet(); } } 


This class is not difficult, as you can see, all words are stored in text files english, transcription and russian, for this you should use the database, but I did not bother much, because everything works like that. The functions of WriteWords, ReadWords serve to save words, it should be noted here that only in order for the function to work, it will need to pass the pointer this from the class that called it. Immediately striking is the fact that all functions are static, this was done on purpose, so as not to duplicate the class many times, everything else is clear and comments will be superfluous. Now that the additional shells are considered, we can describe the add function



 public void AddWord(View view) { CollectionWords.InitializationCollWords(); if(english_language.getText().length() == 0 || russian_language.getText().length() == 0) { Toast toast = Toast.makeText(getApplicationContext(), "  !", Toast.LENGTH_SHORT); toast.show(); return; } if(status != 0 && status == MainActivity.INT_CHG) { CollectionWords.ChangedWordEng(old_english, english_language.getText().toString(), transcription_language.getText().toString().length() == 0 ? "-" : transcription_language.getText().toString(), russian_language.getText().toString()); Back(null); } CollectionWords.PutCollWords(english_language.getText().toString(), (transcription_language.getText().toString().length() == 0 ? "-" : transcription_language.getText().toString()), russian_language.getText().toString()); ClientAddWords caw = new ClientAddWords(); caw.ServerAddWords("1(!!)" + english_language.getText().toString() + "(!!)" + (transcription_language.getText().toString().length() == 0 ? "-" : transcription_language.getText().toString()) + "(!!)" + russian_language.getText().toString()); english_language.setText(""); transcription_language.setText(""); russian_language.setText(""); } 


From the code snippet you can see that the required fields here are enlish_language and russian_language, if they are not filled in, then the word will not be added, the function will end and a message will pop up with a hint. As I said earlier, to add and change words, one xml file is used, and accordingly the class too, therefore there is a second if statement that checks the status variable, storing the value of whether the function was entered into, for word changes.

Of particular interest is the class ClientAddWords, which serves to send a word to the server. Since at the moment, Android Studio requires that everything connected to the network occur in a separate thread, I decided to create a class that is responsible for this. The program has another one that returns words from the server.



As can be seen from the code, the ClientAddWords object is first created, then the object calls the function, it is passed a string separated by the “(!!)” symbol, this symbol separates the opcode intended for the server, in this case it is “1”, and the English word , transcription and translation, it serves to ensure that the server can properly separate data from each other, as you have already guessed, this line is transmitted to the server.



Creating a class to work with the network is very convenient, because the client’s connection to the server goes at the very moment when the ServerAddWords function is called, and after the transfer, the client disconnects from the server application, so there is no additional server load. Below is the ClientAddWords class.



 public class ClientAddWords extends Thread { String str_user; void ServerAddWords(String str) { str_user = str; start(); } public void run() { Log.d("MyLog", "Run Client"); InetAddress addr = null; try { addr = InetAddress.getByName("192.168.1.208"); } catch (UnknownHostException e) { Log.d("MyLog", "ServerAddWords ClientAddWords: " + e); } Client c; try { c = new Client(addr); } catch (IOException e) { Log.d("MyLog", "Socket failed: " + e); return; } c.Out(str_user); c.Close(); } } 


As you can see, in this implementation of the code, there is nothing complicated and it does not require additional explanations, the code of the Client class is presented below.



 public class Client extends Thread { private Socket socket; private BufferedReader in; private PrintWriter out; InetAddress addr; public String In() throws IOException { return in.readLine(); } public void Out(String str) { out.println(str); } public Client(InetAddress addr) throws IOException { this.addr = addr; Log.d("MyLog", "Making client"); try { socket = new Socket(addr, 8080); } catch (IOException e) { Log.d("MyLog", "Socket failed: " + e); throw e; } try { in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true); } catch (Exception e) { Log.d("MyLog", "In/Out: " + e); try { socket.close(); } catch (IOException e2) { Log.d("MyLog", "Client: Socket not closed"); } } } public void Close() { try { socket.close(); in.close(); out.close(); } catch (IOException e) { Log.d("MyLog", "Close Client: " + e); } } } 


There are also no interesting points here, this sample code can be found on any site dedicated to network programming.



Now we will look at the class responsible for changing and deleting words, as I have said more than once, they use one xml file, and the most interesting thing in its implementation is filling in layouts with aa buttons.



 <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/background_find" > <LinearLayout android:id="@+id/ll_find" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> </LinearLayout> </ScrollView> 


In the xml file itself, only this piece of code is of interest, here you can see that the layout is set to id - ll_find, this is necessary in order to create the buttons programmatically.



 class MyButton extends Button { private String str_eng; private String str_trans; private String str_rus; private int index; public MyButton(Context context) { super(context); } void setEnglish(String eng) { str_eng = eng; } void setTranscription(String trans) { str_trans = trans; } void setRussian(String rus) { str_rus = rus; } void setIndex(int id) { index = id; } String getEnglish() { return str_eng; } String getTranscription() { return str_trans; } String getRussian() { return str_rus; } int getIndex() { return index; } } 


I will immediately note this class, as it is not difficult to guess it is intended only for storing card values, namely, English words, its transcription and translation.



The first function to be described is CreateButton, the code is presented below.



 public MyButton CreateButton(int i, String eng, String trans, String rus) { final MyButton btnNew = new MyButton(this); btnNew.setBackgroundResource(R.drawable.background_button); btnNew.setText(eng + " - " + rus); btnNew.setEnglish(eng); btnNew.setTranscription(trans); btnNew.setRussian(rus); btnNew.setIndex(i); if(status == MainActivity.INT_DEL) { btnNew.setCompoundDrawablesWithIntrinsicBounds(R.drawable.icon_delete_button, 0, 0, 0); btnNew.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { AlertDialog.Builder ad; Find context; context = Find.this; String title = " "; String message = " ?"; String button1String = ""; String button2String = ""; ad = new AlertDialog.Builder((Context) context); ad.setTitle(title); ad.setMessage(message); ad.setPositiveButton(button1String, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int arg1) { CollectionWords.DeleteWords(btnNew.getEnglish()); ll_layout.removeView(btnNew); } }); ad.setNegativeButton(button2String, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int arg1) { } }); ad.show(); } }); } else { btnNew.setCompoundDrawablesWithIntrinsicBounds(R.drawable.icon_changed_button, 0, 0, 0); btnNew.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.d("MyLog", "Changed Words"); ChangedWord((MyButton) v); ll_layout.removeView((MyButton) v); } }); } return btnNew; } 


There are a couple of interesting points here, namely changing the background of the button, then, depending on what purpose this class is visited for, creating the icon for the button, the setCompoundDrawablesWithIntrinsicBounds function and the implementation of the setOnClickListener event are responsible for this, or a dialog box is created and the word btnNew is deleted, or the ChangedWord function is called, which opens an activation intended for changing the word.



The next function that needs to be told is ShowViewWords, its purpose is to add buttons to the layout.



 public void ShowViewWords(LinearLayout.LayoutParams lParams, String sub_str) { int i = 0; String first_chr = new String(""); for(Map.Entry<String, TransRus> me : CollectionWords.AllWords()) { if(sub_str.length() != 0 && (me.getKey().toLowerCase().indexOf(sub_str.toLowerCase()) == -1 && me.getValue().setRussian().toLowerCase().indexOf(sub_str.toLowerCase()) == -1)) continue; if(!first_chr.equals(String.valueOf(me.getKey().toUpperCase().charAt(0)))) { first_chr = String.valueOf(me.getKey().toUpperCase().charAt(0)); TextView temp = new TextView(this); temp.setText(first_chr + ":"); temp.setTextSize(25f); ll_layout.addView(temp, i, lParams); i++; } ll_layout.addView(CreateButton(i, me.getKey(), me.getValue().setTranscription(), me.getValue().setRussian()), i, lParams); i++; } if(i == 0) { LinearLayout.LayoutParams l = CreateParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER_VERTICAL); TextView not_found = new TextView(this); not_found.setText("  "); ll_layout.addView(not_found, l); } } 


It also creates and adds a TextView, which stores the meaning of the first letter of a word that is different from the first letter of the next word. I tried to explain as best as possible, but just in case I will give an example as an example.



image



This piece of code is responsible for this.



 if(!first_chr.equals(String.valueOf(me.getKey().toUpperCase().charAt(0)))) { first_chr = String.valueOf(me.getKey().toUpperCase().charAt(0)); TextView temp = new TextView(this); temp.setText(first_chr + ":"); temp.setTextSize(25f); ll_layout.addView(temp, i, lParams); i++; } 


Initially, the variable first_chr is assigned an empty string, so if the loop passes the first time, then the value will be entered into it.



This string is responsible for the loop condition.



 for(Map.Entry<String, TransRus> me : CollectionWords.AllWords()) 


I will tell you about the purpose of the first if statement, since this refers to the search, and I’ll tell you about the search last.



  ll_layout.addView(CreateButton(i, me.getKey(), me.getValue().setTranscription(), me.getValue().setRussian()), i, lParams); 


And for adding to ll_layout, this construct is responsible, here the CreateButton function is called, which was discussed above and returns the value of MyButton, then the index and parameters of this button are added.



The ShowViewWords function is called from the CreatesButton function, and the CreatesButton function is already called from onCreate. The CreatesButton code is shown below.



 public void CreatesButton(String str_find) { ll_layout.removeAllViews(); LinearLayout.LayoutParams lParams = CreateParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, Gravity.LEFT); lParams.topMargin = 1; ShowViewWords(lParams, str_find); } 


CreateParams function code:



 public LinearLayout.LayoutParams CreateParams(int width, int height, int gravity) { LinearLayout.LayoutParams lParams = new LinearLayout.LayoutParams(width, height); lParams.gravity = gravity; return lParams; } 


At this stage of the program description, I approached the implementation of the TestWords class, which is responsible for testing the words. As usual, there is nothing complicated in it, but there are a couple of points that should be considered. The very first one is the choice of the test by the user, no matter how hard it is to guess there may be nine test options, namely the given word order (in alphabetical, in reverse and random) and the object of testing (English, transcription, Russian). So the very first is the StatusTest function. It determines by code which of the Edits should be blocked, and initializes the variable with the index under which the word stands.



 public void StatusTest() { switch (status) { case MainActivity.INT_ALPH_ENG: edit_transcription.setRawInputType(0x00000000); edit_russian.setRawInputType(0x00000000); next_words = 0; break; case MainActivity.INT_ALPH_TRANS: edit_english.setRawInputType(0x00000000); edit_russian.setRawInputType(0x00000000); next_words = 0; break; case MainActivity.INT_ALPH_RUS: edit_english.setRawInputType(0x00000000); edit_transcription.setRawInputType(0x00000000); next_words = 0; break; case MainActivity.INT_REVS_ENG: edit_transcription.setRawInputType(0x00000000); edit_russian.setRawInputType(0x00000000); next_words = CollectionWords.coll_words.size() - 1; break; case MainActivity.INT_REVS_TRANS: edit_english.setRawInputType(0x00000000); edit_russian.setRawInputType(0x00000000); next_words = CollectionWords.coll_words.size() - 1; break; case MainActivity.INT_REVS_RUS: edit_english.setRawInputType(0x00000000); edit_transcription.setRawInputType(0x00000000); next_words = CollectionWords.coll_words.size() - 1; break; case MainActivity.INT_RAND_ENG: rand_next_words = new Random(); next_words = MethodRandomWords(); edit_transcription.setRawInputType(0x00000000); edit_russian.setRawInputType(0x00000000); break; case MainActivity.INT_RAND_TRANS: rand_next_words = new Random(); next_words = MethodRandomWords(); edit_english.setRawInputType(0x00000000); edit_russian.setRawInputType(0x00000000); break; case MainActivity.INT_RAND_RUS: rand_next_words = new Random(); next_words = MethodRandomWords(); edit_english.setRawInputType(0x00000000); edit_transcription.setRawInputType(0x00000000); break; } } 


In the case of alphabetical order, the variable next_words is set to 0, the reverse order is the size of the class TreeMap minus 1 and random order, a special function that returns a random value to next_words.



The MethodRandomWords function serves not to return the same random value several times.



After initializing all Edit'ov and calling the StatusTest function, the ReadWord method is executed.



 public void ReadWord() { last_words++; amount_words.setText(last_words + "/" + CollectionWords.coll_words.size()); switch (status) { case MainActivity.INT_ALPH_ENG: nw = VecNextWord(next_words); edit_english.setText(""); edit_transcription.setText(nw.getValue().setTranscription()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_ALPH_TRANS: nw = VecNextWord(next_words); edit_transcription.setText(""); edit_english.setText(nw.getKey()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_ALPH_RUS: nw = VecNextWord(next_words); edit_russian.setText(""); edit_english.setText(nw.getKey()); edit_transcription.setText(nw.getValue().setTranscription()); break; case MainActivity.INT_REVS_ENG: nw = VecNextWord(next_words); edit_english.setText(""); edit_transcription.setText(nw.getValue().setTranscription()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_REVS_TRANS: nw = VecNextWord(next_words); edit_transcription.setText(""); edit_english.setText(nw.getKey()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_REVS_RUS: nw = VecNextWord(next_words); edit_russian.setText(""); edit_english.setText(nw.getKey()); edit_transcription.setText(nw.getValue().setTranscription()); break; case MainActivity.INT_RAND_ENG: nw = VecNextWord(next_words); edit_english.setText(""); edit_transcription.setText(nw.getValue().setTranscription()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_RAND_TRANS: nw = VecNextWord(next_words); edit_transcription.setText(""); edit_english.setText(nw.getKey()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_RAND_RUS: nw = VecNextWord(next_words); edit_russian.setText(""); edit_english.setText(nw.getKey()); edit_transcription.setText(nw.getValue().setTranscription()); break; } status_true_word.setText(":-"); } 


The purpose of this method is to load the first word, the VecNextWord function is responsible for this, the parameter of which is the index and the return value is Map.Entry <String, TransRus>, and also specify the number of words and reset the status.



The next role is played by only two functions, Check - checks the correctness of the entered word and, if necessary, changes the Status, NextWord - returns the next word in the list, depending on the selected order. The feature code is shown below.



 public void Check(View view) { check_bool = true; Log.d("MyLog", "Status: " + status); switch (status) { case MainActivity.INT_ALPH_ENG: Log.d("MyLog", "Check()"); if(edit_english.getText().toString().equals(nw.getKey())) { Log.d("MyLog", "True"); status_true_word.setText(": "); Log.d("MyLog", "next_words: " + next_words); nw.getValue().getError(true); } else { Log.d("MyLog", "False"); status_true_word.setText(":  "); } break; case MainActivity.INT_ALPH_TRANS: Log.d("MyLog", "Check()"); if(edit_transcription.getText().toString().equals(nw.getValue().setTranscription())) { status_true_word.setText(": "); Log.d("MyLog", "next_words: " + next_words); nw.getValue().getError(true); } else { status_true_word.setText(":  "); } break; case MainActivity.INT_ALPH_RUS: Log.d("MyLog", "Check()"); if(edit_russian.getText().toString().equals(nw.getValue().setRussian())) { status_true_word.setText(": "); Log.d("MyLog", "next_words: " + next_words); nw.getValue().getError(true); } else { status_true_word.setText(":  "); } break; case MainActivity.INT_REVS_ENG: Log.d("MyLog", "Check()"); if(edit_english.getText().toString().equals(nw.getKey())) { status_true_word.setText(": "); Log.d("MyLog", "next_words: " + next_words); nw.getValue().getError(true); } else { status_true_word.setText(":  "); } break; case MainActivity.INT_REVS_TRANS: Log.d("MyLog", "Check()"); if(edit_transcription.getText().toString().equals(nw.getValue().setTranscription())) { status_true_word.setText(": "); Log.d("MyLog", "next_words: " + next_words); nw.getValue().getError(true); } else { status_true_word.setText(":  "); } break; case MainActivity.INT_REVS_RUS: Log.d("MyLog", "Check()"); if(edit_russian.getText().toString().equals(nw.getValue().setRussian())) { status_true_word.setText(": "); Log.d("MyLog", "next_words: " + next_words); nw.getValue().getError(true); } else { status_true_word.setText(":  "); } break; case MainActivity.INT_RAND_ENG: Log.d("MyLog", "Check()"); if(edit_english.getText().toString().equals(nw.getKey())) { status_true_word.setText(": "); Log.d("MyLog", "next_words: " + next_words); nw.getValue().getError(true); } else { status_true_word.setText(":  "); } break; case MainActivity.INT_RAND_TRANS: Log.d("MyLog", "Check()"); if(edit_transcription.getText().toString().equals(nw.getValue().setTranscription())) { status_true_word.setText(": "); Log.d("MyLog", "next_words: " + next_words); nw.getValue().getError(true); } else { status_true_word.setText(":  "); } break; case MainActivity.INT_RAND_RUS: Log.d("MyLog", "Check()"); if(edit_russian.getText().toString().equals(nw.getValue().setRussian())) { status_true_word.setText(": "); Log.d("MyLog", "next_words: " + next_words); nw.getValue().getError(true); } else { status_true_word.setText(":  "); } break; } } public void NextWord(View view) throws InterruptedException { if(last_words >= CollectionWords.coll_words.size()) { ResultTestGo(); return; } if(!check_bool && last_words != 0) Check(view); AddWordInTable(nw.getValue().setError()); last_words++; amount_words.setText(last_words + "/" + CollectionWords.coll_words.size()); switch (status) { case MainActivity.INT_ALPH_ENG: next_words++; nw = VecNextWord(next_words); edit_english.setText(""); edit_transcription.setText(nw.getValue().setTranscription()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_ALPH_TRANS: next_words++; nw = VecNextWord(next_words); edit_transcription.setText(""); edit_english.setText(nw.getKey()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_ALPH_RUS: next_words++; nw = VecNextWord(next_words); edit_russian.setText(""); edit_english.setText(nw.getKey()); edit_transcription.setText(nw.getValue().setTranscription()); break; case MainActivity.INT_REVS_ENG: next_words--; nw = VecNextWord(next_words); edit_english.setText(""); edit_transcription.setText(nw.getValue().setTranscription()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_REVS_TRANS: next_words--; nw = VecNextWord(next_words); edit_transcription.setText(""); edit_english.setText(nw.getKey()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_REVS_RUS: next_words--; nw = VecNextWord(next_words); edit_russian.setText(""); edit_english.setText(nw.getKey()); edit_transcription.setText(nw.getValue().setTranscription()); break; case MainActivity.INT_RAND_ENG: next_words = MethodRandomWords(); nw = VecNextWord(next_words); edit_english.setText(""); edit_transcription.setText(nw.getValue().setTranscription()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_RAND_TRANS: next_words = MethodRandomWords(); nw = VecNextWord(next_words); edit_transcription.setText(""); edit_english.setText(nw.getKey()); edit_russian.setText(nw.getValue().setRussian()); break; case MainActivity.INT_RAND_RUS: next_words = MethodRandomWords(); nw = VecNextWord(next_words); edit_russian.setText(""); edit_english.setText(nw.getKey()); edit_transcription.setText(nw.getValue().setTranscription()); break; } status_true_word.setText(":-"); check_bool = false; } 


, - , . , , Html-, . , , , AddWordInTable(nw.getValue().setError()), .



 public void AddWordInTable(boolean temp) { table_result += "<tr><td " + (temp ? "bgcolor=\"#008000\"" : "bgcolor=\"#FF0000\"") + ">" + nw.getKey() + "</td><td " + (temp ? "bgcolor=\"#008000\"" : "bgcolor=\"#FF0000\"") + ">" + nw.getValue().setTranscription() + "</td><td " + (temp ? "bgcolor=\"#008000\"" : "bgcolor=\"#FF0000\"") + ">" + nw.getValue().setRussian() + "</td><td " + (temp ? "bgcolor=\"#008000\"" : "bgcolor=\"#FF0000\"") + ">" + (temp ? "" : " ") + "</td></tr>\n"; } 


onCreat, ResultTest, .

, , , ResultTest, , , , Html- loadDataWithBaseURL(null, TestWords.table_result, «text/html», «UTF-8», null), WebView.



, . Load, 18 , .. RecyclerView, - , , . , , Load, .



, , , . xml- CheckBox' TextView', . TextView , . , , , , .



, RecyclerView, , .. , .



, onCreateViewHolder, onBindViewHolder, getItemCount, ViewHolder. GetItemCount , .. . ViewHolder.



 public static class ViewHolder extends RecyclerView.ViewHolder { public CheckBox chkbox; public TextView tv_alph; public ViewHolder(View v) { super(v); chkbox = (CheckBox) v.findViewById(R.id.rv_chkbox); tv_alph = (TextView) v.findViewById(R.id.tv_alph); } } 


. onCreateViewHolder, ViewHolder.



 public RecyclerLoad.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.content_checkbox, parent, false); ViewHolder vh = new ViewHolder(v); return vh; } 


onBindViewHolder.



 public void onBindViewHolder(final ViewHolder holder, final int position) { if(index_alph[position]) { holder.tv_alph.setText(Alph[position]); holder.tv_alph.setVisibility(View.VISIBLE); } else holder.tv_alph.setVisibility(View.GONE); holder.chkbox.setText(Eng_Array[position] + " - [" + Trans_Array[position] + "] - " + Rus_Array[position]); if(this_load.menu_load_1 != null) this_load.menu_load_1.setTitle("   (" + Integer.toString(amount) + ")"); holder.chkbox.setOnCheckedChangeListener(null); holder.chkbox.setChecked(checked_box[position]); holder.chkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if(isChecked) checked_words_load++; else checked_words_load--; checked_box[position] = isChecked; if(this_load.menu_load_2 != null) this_load.menu_load_2.setTitle(".   (" + Integer.toString(checked_words_load) + ")"); } }); if (position >= amount - 1) { Log.d("MyLog", "!!!"); LoadWords(sub_str); onBind = true; } } 


, — holder , — CheckBox' setOnCheckedChangeListener setChecked, CheckBox' onCheckedChanged, «» — if , LoadWords.



sub_str, . String, Edit' «: ». Since , Edit'e, .



 find_words.addTextChangedListener(new TextWatcher() { public void afterTextChanged(Editable s) { } public void beforeTextChanged(CharSequence s, int start, int count, int after) { } public void onTextChanged(CharSequence s, int start, int before, int count) { FindWord(null); } }); public void FindWord(View view) { mAdapter.Find(find_words.getText().toString()); mAdapter.notifyDataSetChanged(); } 


, FindWord, Find, RecyclerLoad, , , .



 public void Find(String sub_str) { this.sub_str = sub_str; amount = 0; Eng_Array = null; Trans_Array = null; Rus_Array = null; checked_box = null; index_alph = null; Alph = null; LoadWords(sub_str); } 


LoadWords, RecyclerLoad , .. .



 public void LoadWords(String sub_str) { ClientLoadWords clw = new ClientLoadWords(); clw.LoadWords("2(!!)" + (sub_str.length() != 0 ? sub_str : "(--)"), amount); try { clw.join(); } catch (InterruptedException e) { Log.d("MyLog", "ShowViewWords: " + e); } if(clw.int_error == -1) { Toast toast = Toast.makeText(this_load.getApplicationContext(), "   !", Toast.LENGTH_SHORT); toast.show(); } amount += clw.amount; Log.d("MyLog", "amount = " + amount); String [] temp_Eng_Array = new String[amount]; String [] temp_Trans_Array = new String[amount]; String [] temp_Rus_Array = new String[amount]; String [] temp_Alph = new String[amount]; boolean [] temp_checked_box = new boolean[amount]; boolean [] temp_index_alph = new boolean[amount]; int temp_amount = Eng_Array != null ? Eng_Array.length : 0; if(Eng_Array != null) for(int i = 0; i < Eng_Array.length; i++) { temp_Eng_Array[i] = Eng_Array[i]; temp_Trans_Array[i] = Trans_Array[i]; temp_Rus_Array[i] = Rus_Array[i]; temp_Alph[i] = Alph[i]; temp_checked_box[i] = checked_box[i]; temp_index_alph[i] = index_alph[i]; } for(int i = 0; i < clw.amount; i++) { temp_Eng_Array[i + temp_amount] = clw.Eng_Array[i]; temp_Trans_Array[i + temp_amount] = clw.Trans_Array[i]; temp_Rus_Array[i + temp_amount] = clw.Rus_Array[i]; temp_checked_box[i + temp_amount] = false; temp_index_alph[i + temp_amount] = false; temp_Alph[i + temp_amount] = ""; if(!first_chr.equals(String.valueOf(clw.Eng_Array[i].toUpperCase().charAt(0)))) { Log.d("MyLog", "First Chr: " + first_chr + ", me.getKey(): " + clw.Eng_Array[i].toUpperCase().charAt(0) + " boolean: " + first_chr.equals(String.valueOf(clw.Eng_Array[i].toUpperCase().charAt(0)))); first_chr = String.valueOf(clw.Eng_Array[i].toUpperCase().charAt(0)); temp_Alph[i + temp_amount] = first_chr + ":"; temp_index_alph[i + temp_amount] = true; } } for(int i = 0; i < temp_Eng_Array.length; i++) { Log.d("MyLog", "temp_Alph: " + temp_Alph[i] + ", temp_index_alph = " + temp_index_alph[i] + ", i = " + i); } Eng_Array = temp_Eng_Array; Trans_Array = temp_Trans_Array; Rus_Array = temp_Rus_Array; checked_box = temp_checked_box; index_alph = temp_index_alph; Alph = temp_Alph; } 


LoadWords , . - ClientLoadWords — ClientAddWords, , . . LoadWords, , , . LoadWords .



 public void run() { InetAddress addr = null; try { addr = InetAddress.getByName("192.168.1.137"); } catch (UnknownHostException e) { Log.d("MyLog", "ClientLoadWords LoadWords 1: " + e); } Client c; try { c = new Client(addr); } catch (IOException e) { Log.d("MyLog", "Socket failed: " + e); int_error = -1; return; } c.Out(str_user); c.Out(Integer.toString(begin)); amount = 0; try { amount = Integer.parseInt(c.In()); } catch (IOException e) { Log.d("MyLog", "LoadWords ClientLoadWords 3: " + e); } Log.d("MyLog", "Amount: " + amount); Id_Array = new int[amount]; Eng_Array = new String[amount]; Trans_Array = new String[amount]; Rus_Array = new String[amount]; try { for (int i = 0; i < amount; i++) { Id_Array[i] = Integer.parseInt(c.In()); Eng_Array[i] = c.In(); Trans_Array[i] = c.In(); Rus_Array[i] = c.In(); } } catch (IOException e) { Log.d("MyLog", "LoadWords ClientLoadWords 4: " + e); } Sort(); } 


, . , , for, , , .



LoadWords. clw.join() ClientLoadWords, . clw -1, . , , , TextView' index_alph, TextView .



, , .. , , , , . ., , « », , , Html-, , .





, , MySQL TCP, , . / ServerOneJabber. Thread. , .. .



 public ServerOneJabber(Socket s) throws IOException, SQLException { socket = s; in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true); sqldb = new SqlDB(); start(); } 


, sqldb, , , . in out In Out, .



 public void run() { String message_user = new String(""); try { message_user = Out(); } catch(IOException e) { System.out.println(e); } System.out.println("message_user: " + message_user); try { switch(message_user.charAt(0)) { case '1': AddWord(message_user); break; case '2': TransferWord(message_user); break; } } catch(SQLException e) { System.out.println(e); } catch(IOException e) { System.out.println(e); } } 


run . .



 public void AddWord(String str) throws SQLException { String[] str_user = Split(str, "(!!)"); for(int i = 0; i < str_user.length; i++) System.out.println("str_user: " + str_user[i]); sqldb.AddWord(str_user[1], str_user[2], str_user[3]); } 


AddWord . sqldb AddWord. Split , , split String , .



 public void TransferWord(String str) throws SQLException, IOException { String [] user_str = Split(str, "(!!)"); for(int i = 0; i < user_str.length; i++) { System.out.println("user_str: " + user_str[i]); } if(sqldb.CountSQL() == 0) { In("0"); return; } int begin = new Integer(Out()); System.out.println("Loading Words..."); String [] data; if(user_str[1].equals("(--)")) data = sqldb.AllWords(); else data = sqldb.Find(user_str[1]); read_amount_words = (data.length - begin > 100 ? 100 : data.length - begin); In(Integer.toString(read_amount_words)); for(int i = begin; i < begin + ((data.length - begin) > 100 ? 100 : data.length); i++) { System.out.println("i = " + i + ", data.length = " + data.length); if(i == data.length) break; String [] str_data = Split(data[i], "(!!)"); for(int j = 0; j < str_data.length; j++) System.out.println("str_data: " + str_data[j]); In(str_data[0]); In(str_data[1]); In(str_data[2]); In(str_data[3]); } } 


TransferWord . , , , , , , . , 100 , 100 , , .



 public class Server { static final int PORT = 8080; static public void main(String[] args) throws IOException { ServerSocket s = new ServerSocket(PORT); System.out.println("Server Started"); try { while(true) { Socket socket = s.accept(); try { System.out.println("Client Connection"); new ServerOneJabber(socket); } catch(IOException e) { socket.close(); } } } catch(SQLException e) { System.out.println(e); } finally { s.close(); } } } 


Server main, , ServerOneJabber .



Conclusion



. , , , , - . - , , . .

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



All Articles