3r3-31.

# The purpose of article

3r3777.
This article will address the problems of Android development and development in general. We all know that the development of a program is a big complex work that takes a lot of time and effort, and sometimes you have to spend a lot of time to find a solution to a problem, because some solutions from the Internet do not always work. 3r3777.
3r3777.
3r3777.
3r314.
Custom keyboard for Android

Advertising integration in the program 3r349.
3r3777.

## Custom keyboard for Android

3r3777.
In my program, in my calculator, I had to make my keyboard, as it is not convenient to enter mathematical formulas from the system keyboard. Trying to solve this problem, I went through a bunch of forums, tried out several different solutions, but they all did not give the proper result. 3r3777.
3r3777.
3r? 3516. Let's start:
3r3777.
3r340.
Create a new project in android studio.

Create a pair of classes

Test application 3r349.
3r3777.
Make a simple keyboard of 9 characters with the ability to delete these characters. 3r3777.
Let's call our project KeyBoardTest

3r3777.
3r360. 3r3777.
3r3777.
Select an empty activator and start 3r-33677.
3r3777.
3r3777.
3r3777.
Finish we created our new project. Now let's do the most basic, namely, create a layout file in the folder - res /layout and call it keyboard, here we will have the appearance of the keyboard. 3r3777.
3r376.
3r3777.
Draw this keyboard:

3r3777.
3r33625. 3r33587. 3r33434.
3r388. xmlns: android = "http://schemas.android.com/apk/res/android" android: layout_width = "match_parent"
android: layout_height = "match_parent">
3r33588. android: id = "@ + id /one"
android: textColor = "@ color /colorWhite"
android: gravity = "center"
android: textSize = "30sp"
android: text = "@ string /one"
android: layout_weight = "1"
android: layout_width = "0dp"
android: layout_height = "match_parent" />
3r33588. android: id = "@ + id /two"
android: textColor = "@ color /colorWhite"
android: gravity = "center"
android: textSize = "30sp"
android: text = "@ string /two"
android: layout_weight = "1"
android: layout_width = "0dp"
android: layout_height = "match_parent" />
3r33588. android: id = "@ + id /three"
android: textColor = "@ color /colorWhite"
android: gravity = "center"
android: textSize = "30sp"
android: text = "@ string /three"
android: layout_weight = "1"
android: layout_width = "0dp"
android: layout_height = "match_parent" />
3r33588. android: id = "@ + id /four"
android: textColor = "@ color /colorWhite"
android: gravity = "center"
android: textSize = "30sp"
android: text = "@ string /four"
android: layout_weight = "1"
android: layout_width = "0dp"
android: layout_height = "match_parent" />
3r33588. android: id = "@ + id /five"
android: textColor = "@ color /colorWhite"
android: gravity = "center"
android: textSize = "30sp"
android: text = "@ string /five"
android: layout_weight = "1"
android: layout_width = "0dp"
android: layout_height = "match_parent" />
3r33479.
3r33588. android: id = "@ + id /six"
android: textColor = "@ color /colorWhite"
android: gravity = "center"
android: textSize = "30sp"
android: text = "@ string /six"
android: layout_weight = "1"
android: layout_width = "0dp"
android: layout_height = "match_parent" />
3r33588. android: id = "@ + id /seven"
android: textColor = "@ color /colorWhite"
android: gravity = "center"
android: textSize = "30sp"
android: text = "@ string /seven"
android: layout_weight = "1"
android: layout_width = "0dp"
android: layout_height = "match_parent" />
3r33588. android: id = "@ + id /eight"
android: textColor = "@ color /colorWhite"
android: gravity = "center"
android: textSize = "30sp"
android: text = "@ string /eight"
android: layout_weight = "1"
android: layout_width = "0dp"
android: layout_height = "match_parent" />
3r33588. android: id = "@ + id /nine"
android: textColor = "@ color /colorWhite"
android: gravity = "center"
android: textSize = "30sp"
android: text = "@ string /nine"
android: layout_weight = "1"
android: layout_width = "0dp"
android: layout_height = "match_parent" />
3r33588. android: id = "@ + id /delete"
android: textColor = "@ color /colorWhite"
android: gravity = "center"
android: textSize = "30sp"
android: text = "@ string /delete"
android: layout_weight = "1"
android: layout_width = "0dp"
android: layout_height = "match_parent" />
3r33479.
3r33479.
3r3630. 3r3777.
After our keyboard is drawn, we can create a class that will register all of our keystrokes and write what we need. Please note that every textview has an id - this is very important! 3r3777.
3r3777.
Let's call this class KeyBoardListener. 3r3777.
3r3777.
Let's write the constructor of our class, it takes the MainActivity as arguments - the field in which we work, in other words, the location of our editText, and also it takes the editText itself, in which we will type characters from our keyboard. 3r3777.
3r3777.
3r33625. ` package keyboard.develop.keyboardtest;import android.content.Context;import android.view.View;import android.widget.EditText;import android.widget.TextView;public class KeyBoardListener {EditText editText;private StringBuilder finalText = new StringBuilder ();KeyBoardListener (MainActivity view, final EditText editText) {this.editText = editText;TextView one = view.findViewById (R.id.one);TextView two = view.findViewById (R.id.two);TextView three = view.findViewById (R.id.three);TextView four = view.findViewById (R.id.four);final TextView five = view.findViewById (R.id.five);TextView six = view.findViewById (R.id.six);TextView seven = view.findViewById (R.id.seven);TextView eight = view.findViewById (R.id.eight);TextView nine = view.findViewById (R.id.nine);TextView delete = view.findViewById (R.id.delete);one.setonclickListener (new View.onclickListener () {@Override) . setTextSelection ();}});two. . setTextSelection ();}});three. . setTextSelection ();}});four.setonclickListener (new View.onclickListener () {@Override) . setTextSelection ();}});five.setonclickListener (new View.onclickListener () {@Overridepublic void onclick (View view) {int selection = editText.getSelectionEnd ();finalText.insert (selection, "5");setTextSelection ();}});six. . setTextSelection ();}});seven. . setTextSelection ();}});eight. . setTextSelection ();}});nine. . setTextSelection ();}});delete. . finalText = stringToBuilder ((selection == editText.length () - 1)? finalText.substring (? finalText.length () - 2): finalText.substring (? selection - 1) + finalText.substring (selection) );EditText.setText (finalText);.}Private StringBuilder stringToBuilder (String s) {return new StringBuilder (s);}Private void setTextSelection () {Int selection = editTextartartr. 89 editText.setText (finalText);editText.setSelection (selection + 1);}}` 3r3630. 3r3777.
Now let's take a closer look at this code. In the constructor we passed the editText and activations in order to take the buttons and assign them the execution of the input. It should be noted that the “button” method is used in the delete button method, in other words, it is an abbreviated code entry. Not everyone knows this design, so I decided that we should pay attention to it. This is especially useful for beginners. 3r3777.
3r3777.
This construction works in this way

3r3777.
3r33625. ` int p = (condition)? option 1: option 2;int p = k == 2? 7: 3;//it can be written and soif (k = 2)p = 7;elsep = 3;` 3r3630. 3r3777.
But we have moved away from the topic. Now after our constructor is ready, and we can respond to button presses, we can use our class. First we need to call this class in our main activity 3r3-3777.
3r3777.
3r33625. ` package keyboard.develop.keyboardtest;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.view.WindowManager;import android.widget.EditText;import android.widget.LinearLayout;public class MainActivity extends AppCompatActivity {private LinearLayout layout;@Overrideprotected void onCreate (Bundle savedInstanceState) {getWindow (). setFlags (WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);super.onCreate (savedInstanceState);setContentView (R.layout.activity_main);final EditText editText = findViewById (R.id.edit);KeyBoardListener keyBoardListener = new KeyBoardListener (this, editText);layout = findViewById (R.id.keyBoard);editText.setonclickListener (new View.onclickListener () {@Override}@Overridepublic void onBackPressed () {layout.setTranslationY (250); //The keyboard goes off the screen -disappears.}}` 3r3630. 3r3777.
It is worth paying attention to this line

3r3777.
3r33625. ` getWindow (). setFlags (WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);` 3r3630. 3r3777.
In this line, we disable the system keyboard, but leave the cursor so that we can move between characters and insert numbers /letters, etc. That is precisely why we used the class 3r-33333 in the code above. StringBuilder [/i] and method 3r33333. insert [/i] . 3r3777.
3r3777.
It is also very important that we do not call the hide () method for our keyboard, but simply remove it off the screen. You will probably ask the question: “Why won't we make hide or call the method gone?” And I’ll answer you, this is connected with the greedy android garbage collector. If we call this method, then all the pointers to the buttons will disappear, and all responses will not work. 3r3777.
Now you can ask: “Why can't we call the constructor again and just reassign everything?”. And I will answer you that the whole thing is that this is a rather demanding process, and in the process of recalling, some problems arise when working with memory, which causes the application to crash, but simply calling setTranslationY () is more convenient and easier, especially since we don’t prevents to remove the keyboard or lift it. Due to the fact that this whole method is called as a separate class, we can add it anywhere and use it in any programs. Thus, the objectivity of the code is obtained. 3r3777.
3r3777.
But I did not show you how to do this in the xml code, how to specify the location of this keyboard, and everything is very simple

3r3777.
3r33625. 3r33587. 3r33434.
3r33588. android: textColor = "@ color /colorPrimary"
android: gravity = "center"
android: textSize = "25sp"
android: layout_width = "match_parent"
android: layout_height = "50dp"
android: text = "Write your text here!" />
3r33464. android: id = "@ + id /edit"
android: layout_width = "match_parent"
android: layout_height = "50dp" />
3r33479.
3r33471. android: translationY = "100dp"
android: id = "@ + id /keyBoard"
android: layout_height = "wrap_content"
android: layout_width = "match_parent"
android: layout_gravity = "bottom">
3r37777. //Or rather, in this line
3r33479.
3r3630. 3r3777.
Now with light manipulations we can use our keyboards anywhere, even in fragments. 3r3777.
3r3777.
In our application, the keyboard looks like this

3r3777.
3r3777.
3r3777.
3r301501. 3r? 3516. Multithreading 3r33517. 3r3504. 3r3777.
Multi-threading - it is clear from the name that this is a lot of threads. A lot of threads - this means the execution of several operations simultaneously. Multithreading is a rather problematic topic in programming. What's in C ++, what's in Java, that in other languages ​​with multithreading there have always been problems. Fortunately, almost all languages ​​have a high-level solution to this problem. But we are currently developing for Android, so we’ll talk about Anroid, or rather about the Java programming language. 3r3777.
3r3777.
In Java, Java has such a thing as Thread - it is convenient when drawing, with frequent instant redrawing of the image, there are many articles on this topic, including on Habré, so I will not consider this option. I am interested in the so-called “falling asleep stream”, the stream that is waiting for its call to solve any task. This is the case when you caused the flow, it worked and fell asleep, without spending the device resources while waiting for a new task. 3r3777.
3r3777.
And the name of what I described above is the Android Java 3r33333 library. 3r? 3516. ExecutorServise
3r3634. 3r3777.
3r3777.
The essence of this class is that it can reuse the same stream without creating a new one. And now we will consider how it works, we will not create a new program, but continue to work in ours. 3r3777.
3r3777.
To do this, create a new class, which will be called ExecutorThread. We set the task that we need to add to the number 3r-33333. p [/i] unit until it is p will not be equal to the number we entered in 4 degrees. Everything is done to make the calculation longer. And so that the whole interface does not hang, we will put it all into a separate thread. 3r3777.
3r3777.
3r33625. ` package keyboard.develop.keyboardtest;import android.widget.TextView;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ExecutorThread {private ExecutorService executorService;private thread thread;private int p = 0;private int pow = 0;private int k = 0;private TextView textView;ExecutorThread (final TextView text) {p = 0;textView = text;thread = new Thread (new Runnable () {@Overridepublic void run () {for (int i = 0; i < pow; i++)p ++; 3rr6868. String s = "Result" + k + "^ 4 = "+ String.valueOf (p);TextView.setText (s);}});Thread.start (); 3r3689.}3r3689. void doWork () {executorService = Executors.newSingleThreadExecutor ();executorService.submit (thread);}void setK (int k) {p = 0;this.k = k;pow = (int) Math.pow (k, 4);textView.setText ("Please wait. We are calcing!");}}` 3r3630. 3r3777.
As we see, at that moment, while we did not consider it yet, then we can see the entry “Please wait. We are calcing! ”, That is clear -“ Please wait. We believe!". And after we calculate, we will display the text in our textView, which we passed to the constructor of our class. In order for everything to work, we need to add a textView after our editText to our activity_main, which we had when creating a project. 3r3777.
3r3777.
3r33625. 3r33587. 3r33588. android: gravity = "center"
android: textColor = "@ color /colorPrimary"
android: textSize = "25sp"
android: id = "@ + id /textView"
android: layout_width = "match_parent"
android: layout_height = "50dp" />
3r3630. 3r3777.
And we also need to add the code below to our main class, MainActivity. 3r3777.
3r3777.
3r33625. ` executorThread = new ExecutorThread ((TextView) findViewById (R.id.textView));editText.addTextChangedListener (new TextWatcher () {@Override public void beforeTextChanged (CharSequence charSequence, int i, int i? int i2)} {}) {}@OverridePublic void afterTextChanged (Editable editable) {If (! Editable.toString (). Equals ("")) {ExecutorThread.setK (Integer.parseInt (edit4) edit.end-editte. .toString ()));executorThread. doWork ();}}});` 3r3630. 3r3777.
It is worth noting that the addTextChangeListener method is responsible for changing the text in our editText. As we can see, inside this method we call the doWork () function, which in turn executes these lines

3r3777.
3r33625. ` executorService = Executors.newSingleThreadExecutor ();executorService.submit (thread);` 3r3630. 3r3777.
So what do these lines mean, judging by the name of the function 3r33333. newSingleThreadExecutor () [/i] it is clear that a “new stream” is being created, more precisely, the processor time is allocated for a new stream. And then in the next line we launch a new thread, or rather the old one, which was launched when we called the constructor of our class. 3r3777.
3r3777.
I checked all of the above on my phone, so if you did everything right, then you should have no problems or errors. 3r3777.
3r3777.
As we can see, this method is quite convenient and easy to understand, I tried to describe everything as simply as possible, so I hope you understand everything, but I did not miss anything. 3r3777.
3r3777.
And now let's move on to point 3 of our article, namely, the integration of advertising. 3r3777.
3r3777.
3r3777.
In fact, I can’t tell a lot about this, I can only advise. With advertising, not everything is so easy and transparent. Personally, I would advise you to use Appodeal, it is not so long ago on the market, but it works quite successfully. 3r3777.
3r3777.
It is also worth noting that there is a very good Russian-language support, which almost always immediately answers your question or your problem. This immediately makes it clear how loyal this network is. 3r3777.
3r3777.
I want to say right away, if you suddenly use it, be sure to set up payment in AdMob and in Appodeal, otherwise the advertisement will simply not be loaded. Due to the fact that I did not set up accounts, I wasted all day, and then they told me in support: “Did I set up accounts?”. And after I did it, the advertisement appeared 2 hours later. 3r3777.
3r3777.
3r3667. Conclusion 3r3668. 3r3777.
Later, I will compile a zip archive of our example and drop it somewhere on disk. And then leave a link here to download. 3r3777.
3r3777.
Since this article is intended for novice programmers, I want to note one obvious thing. If you really like programming, and you are ready to spend tons of hours on solving a particular problem, then programming is yours, otherwise there isn’t. Just do not go beyond. Since it’s too long a decision, something not too complicated and not too simple is not good. But this is an obvious fact. In fact, I read this phrase somewhere on the Internet. In fact, it is true. If you think about it, then really, if programming, serious programming would be so easy, then a small part of people from the total number of all people would not be involved in it. 3r3777.
3r3777.
I hope that my article turned out to be useful to someone and really helped someone, helped save time, because I personally, on the keyboard, it would seem such a simple thing, killed 3 days, and it took me 2 streams and the search for a normal solution. of the day
3r38282. ! function (e) {function t (t, n) {if (! (n in e)) {for (var r, a = e.document, i = a.scripts, o = i.length; o-- ;) if (-1! == i[o].src.indexOf (t)) {r = i[o]; break} if (! r) {r = a.createElement ("script"), r.type = "text /jаvascript", r.async =! ? r.defer =! ? r.src = t, r.charset = "UTF-8"; var d = function () {var e = a.getElementsByTagName ("script")[0]; e.parentNode.insertBefore (r, e)}; "[object Opera]" == e.opera? a.addEventListener? a.addEventListener ("DOMContentLoaded", d,! 1): e.attachEvent ("onload", d ): d ()}}} t ("//mediator.mail.ru/script/2820404/"""_mediator") () ();
+ 0 -