Communication between ACTIVITY and SERVICE. Switch between application screens Data transmission between activati
Somehow I had a task to transfer data from the service to activat. The search for solutions in the standard SDK began, but since there was no time, then flew a bad solution as a database use. But the question was opened and after some time I figured out with a more correct way, which is in SDK - using the Classes of Message, Handler, Messenger.
Idea
We need to transmit data from activat to service and back. How do we do it? To solve our task, we already have everything you need. All you need is to bind service to ATITIVITY using Bindservice, transfer the desired parameters and a bit of magic in the form of using Message classes. And magic is to use the MESSAGE instance variables and in particular replyto. This variable is needed to us so that we can refer to the Messanger service instance from activati \u200b\u200band in the service to the MESSANGER-A copy. In fact, not so simple. At least for my not the most gifted mind. In part, I just improve the documentation that already is - Services also, there is good example on stackoverflow. In any case, I hope the article will be helpful at least someone and I did not dare not in vain.
Example
As an example, we are implementing a service that will increase and reduce the value of the counter and return the result in activati \u200b\u200bin TextView. The layout code is omitted, for there are two buttons and a text field - everything is simple.
Sales
I will give a fully activat code:
Public class MainActivity extends Activity (public static final String TAG \u003d "TestService"; TestServiceConnection testServConn; TextView testTxt; final Messenger messenger \u003d new Messenger (new IncomingHandler ()); Messenger toServiceMessenger; @Override public void onCreate (Bundle savedInstanceState) (super. ONCREATE (SAVEDINSTANCESTATE); setContentView; TestTxtXT \u003d (textView) FindViewByid (R.ID.Test_TXT); Bindservice (New Intent), (TestServconn \u003d New TestServiceConnection ()), Context .Bind_auto_create);) @Override public void onestroy () (super.ondestroy (); unbindservice (TestServconn);) Public Void CountinCrClick (View Button) (NULL, TestService.count_Plus); msg.replyto \u003d Messenger; Try (ToserviceMessenger.send (MSG);) Catch (E.PrintStackTrace ();)) Public Void CountdeCrClick (View Button) (NULL, TestService.count_minus); MSG .replyto. \u003d messenger; Try (ToserviceMessenger.send (MSG);) Catch (E.PrintStackTrace ();)) Private Class Incominghandler Extends Handler (@Override Public Void Handlemessage (MSG.What) (CASE TestService. Get_Count: log.d (Tag, "(Activity) ... Get Count"); testtxt.settext ("" + msg.arg1); break;))) Private Class TestServiceConnection Implements ServiceConnection (@Override Public Void OnserviceConnected (Componentname Name, Ibinder Service) (ToserviceMessenger \u003d New Messenger; // Send the initial value of the Message MSG \u003d Message.Obtain counter (NULL, TestService.Set_Count); MSG.ReplyTo \u003d Messenger; msg.arg1 \u003d 0; // Our counter Try (ToserviceMessenger.send (MSG);) Catch (RemoteException E) (E.PrintStackTrace ();)) @Override public void onservicedisconnected (Componentname Name)))
I will explain. When creating activat, we are immediately tied to the service, implementing the ServiceConnection interface and send a message to the "Set the counter value" service, passing zero and creating a ToserviceMessanger, passing the iBinder interface to the designer. By the way, in the service it is necessary to return this ehemple, otherwise there will be NPE. With this class, we send the message to the service. And here it is magic - we save our other Messenger instance to the replyto variable - the one that receives a response from the server and it is through it that will communicate with activat.
To receive a message from the service, use your handler and just looking for variables we need and make action on them. By clicks on the buttons (CountinCrCrClick, CountdeCrClick methods), send requests to the service, specifying the desired action in the MSG.What variable.
Package com.example.servicetest; Import Android.app.Service; Import android.content. *; Import Android.os. *; Import android.os.Process; Import android.util.log; public class TestService extends Service (public static final int COUNT_PLUS \u003d 1; public static final int COUNT_MINUS \u003d 2; public static final int SET_COUNT \u003d 0; public static final int GET_COUNT \u003d 3; int count \u003d 0; IncomingHandler inHandler; Messenger messanger; Messenger toActivityMessenger; @Override public void onCreate () (super.onCreate (); HandlerThread thread \u003d new HandlerThread ( "ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND); thread.start (); inHandler \u003d new IncomingHandler (thread.getLooper ()); messanger \u003d New Messenger (InHandler);) @Override Public iBinder Onbind (Return Messanger.getBinder ();) @Override Public Intent OnStartCommand (Return Start_Sticky;) // Message handler Activities Private Class Incominghandler Extends Handler (Super Looper) (Looper Looper) (Looper Looper) @Override Public Void Handlemessage (Message MSG) (//super.handlemessage(msg); toactivityMess enger \u003d msg.replyto; Switch (MSG.What \u003d MSG.ARG1; log.d (mainactivity.tag, "(Service) ... Set Count"); Break; Case Count_Plus: Count ++; log.d (MainActivity.tag , "(Service) ... Count Plus"); break; Case Count_minus: log.d (mainactivity.tag, "(service) ... count minus"); count--; break;) // Send a meter value In activativity Message Outmsg \u003d Message.Obtain (INHANDER, GET_COUNT); outmsg.arg1 \u003d count; outmsg.replyto \u003d Messanger; Try (if (toactivityMessenger! \u003d NULL) toactivityMessenger.send (Outmsg);) Catch (E.PrintStackTrace ();))))
All by analogy with logic in activiti. I do not even know if you need to explain something. The only moment is that I immediately send a request back to activat in Handlemessage, using the magic variable replyto and pulling the above Messenger above. And the second moment I already said is:
@Override Public iBinder Onbind (Intent Arg0) (Return Messanger.GetBinder ();)
without which everything falls. It is this interface instance that will be transmitted to ServiceConnection.
Conclusion
In general, everything. Such a contrived example of interaction of activat and service. It seems to me that the non-trivial interaction is pretty, although someone may seem otherwise.
Questions, clarifications and other in PM. There may be inaccuracies about any aspects, so feel free to write and straighten.
I hope the post was useful to readers.
Last updated: 04/03/2018
To transfer data between two ACTIVITY, an Intent object is used. Through its Putextra () method, you can add the key and the associated value.
For example, transmitting from the current Activity in the Secondactivity "Hello World" strings with the key "Hello":
// Creating an INTENT object to launch Secondactivity Intens Intens \u003d New Intent (this, secondactivity.class); // Transfer of an object with the "Hello" key and the "Hello World" value of Intent.Putextra ("Hello", "Hello World"); // Starting Secondactivity Startactivity (Intent);
The Putextra () method is used to transmit data, which as a value allows you to transfer the simplest types of type data - String, Int, Float, Double, Long, Short, Byte, Char, the arrays of these types, or the Serializable interface object.
To get the sent data when loading Secondactivity, you can use gET.(), in which the object is transmitted:
Bundle arguments \u003d getintent (). GetExtras (); String Name \u003d Arguments.get ("Hello"). Tostring (); // Hello WORLD.
Depending on the type of data sent, when received, we can use a number of Bundle object methods. All of them accept the object key as a parameter. The main ones are:
get (): universal methodwhich returns the value of the Object type. Accordingly, the receipt field must be converted to the desired type
getString (): Returns the object type String
getint (): Returns the value of type int
getByte (): Returns the value of the BYTE type
getchar (): Returns the value of type char
getShort (): Returns a value of type short
getlong (): Returns a Long value
getfloat (): Returns the value of type Float
getDouble (): Returns a Double value
getBoolean (): Returns a value of type boolean
getchararray (): Returns an array of CHAR objects
getintarray (): Returns an array of int objects
getfloatarray (): Returns an array of Float objects
getSerializable (): Returns the Serializable interface object
Let us in the project will be defined two ACTIVITY: MainActivity and Secondactivity.
In the Secondactivity code we will determine the data obtaining:
Package com.example.eugene.serializeApp; Import android.Support.v7.app.appCompatactivity; Import android.os.Bundle; Import android.widget.textView; public class SecondActivity extends AppCompatActivity (@Override protected void onCreate (Bundle savedInstanceState) (super.onCreate (savedInstanceState); TextView textView \u003d new TextView (this); textView.setTextSize (20); textView.setPadding (16, 16, 16, 16 ); Bundle arguments \u003d getIntent (). GetExtras (); if (arguments! \u003d NULL) (String Name \u003d Argments.get). Tostring (); String Company \u003d Arguments.getString ("Company"); int Price \u003d arguments.getint ("Price"); textView.setText ("Name:" + Name + "\\ Ncompany:" + Company + "\\ Nprice:" + Price);) SetContentView (textView);))
In this case, in the Secondactivity we get all the data from the Bundle object and display them in the TextView text box. It is assumed that this ACTIVITY will be transmitted three elements - two rows with Name and Company keys and a key with a key Price.
Now we will define the transfer to the Secondactivity of the data. For example, we define the next interface for the MainActivity in the Activity_Main.xml file:
Here are three text fields for data entry and a button.
In the MainActivity class we define the following contents:
Package com.example.eugene.serializeApp; Import android.Content.intent; Import android.Support.v7.app.appCompatactivity; Import android.os.Bundle; Import Android.View.View; Import Android.widget.EditText; public class MainActivity extends AppCompatActivity (@Override protected void onCreate (Bundle savedInstanceState) (super.onCreate (savedInstanceState); setContentView (R.layout.activity_main);) public void onClick (View v) (final EditText nameText \u003d findViewById (R.id .name); Final editText CompanyText \u003d FindViewByid (r.id.company); Final EditText Prictext \u003d FindViewBYID (R.ID.Price); String Name \u003d NameText.getText (). Tostring (); String Company \u003d CompanyText.getText ( ) .Tostring (); int Price \u003d Integer.Parseint (prictext.gettext (). Tostring ()); Intens Intens \u003d New Intent (This, SecondActivity.class); Intent.Putextra ("Name", Name); Intent. Putextra ("Company", Company); INTENT.PUTEXTRA ("Price", Price); StartActivity (Intent);))
In the button pressing the button, you get the data entered in text fields, data and transmit them to the Intent object using the Putextra () method. Then launch Secondactivity.
As a result, when you click on the button starts the Secondactivity, which will receive some data entered in text fields.
Transfer of complex objects
In the example, simple data was transmitted - numbers, lines. But we can also transmit more difficult data. In this case, the serialization mechanism is used.
For example, let us in the project will be defined by the Product class:
Package com.example.eugene.serializeApp; Import java.io.serializable; Public Class Product Implements Serializable (Private String Name; Private String Company; PRIVATE INT Price; Public Product (String Name, String Company, Int Price) (this.name \u003d Name; this.price \u003d Company; this.price \u003d Price;) Public String GetName () (RETURN NAME;) Public Void SetName (String Name) (this.name \u003d name;) Public String GetCompany () (Return Company;) Public Void SetCompany (String Company) (this.company \u003d Company;) Public Int GetPrice () (Return Price;) Public Void SetPrice (int price) (this.price \u003d;))
It is worth noting that this class implements the Serializable interface. Now you will change the MainActivity code:
Package com.example.eugene.serializeApp; Import android.Content.intent; Import android.Support.v7.app.appCompatactivity; Import android.os.Bundle; Import Android.View.View; Import Android.widget.EditText; public class MainActivity extends AppCompatActivity (@Override protected void onCreate (Bundle savedInstanceState) (super.onCreate (savedInstanceState); setContentView (R.layout.activity_main);) public void onClick (View v) (final EditText nameText \u003d findViewById (R.id .name); Final editText CompanyText \u003d FindViewByid (r.id.company); Final EditText Prictext \u003d FindViewBYID (R.ID.Price); String Name \u003d NameText.getText (). Tostring (); String Company \u003d CompanyText.getText ( ) .tostring (); int Price \u003d Integer.Parseint (prictext.gettext (). Tostring ()); Product Product \u003d New Product (Name, Company, Price); INTENT INTENT \u003d NEW INTENT (THIS, SECONDACTIVITY.CLASS); INTENT.PUTEXTRA (product.class.getSimpleName (), Product); Startactivity (Intent);))
Now, instead of three scattered data, one Product object is transmitted. As a key, the result is the result of the product.class.getSimpleName () method, which is essentially returning the name of the class.
And change the Secondactivity class:
Package com.example.eugene.serializeApp; Import android.Support.v7.app.appCompatactivity; Import android.os.Bundle; Import android.widget.textView; public class SecondActivity extends AppCompatActivity (@Override protected void onCreate (Bundle savedInstanceState) (super.onCreate (savedInstanceState); TextView textView \u003d new TextView (this); textView.setTextSize (20); textView.setPadding (16, 16, 16, 16 ); Bundle arguments \u003d getIntent (). GetExtras (); Final Product Product; if (arguments! \u003d NULL) (Product \u003d (Product) Arguments.GetSerializable (Product.class.GetSimpleName ()); textView.settext ("Name: "+ Product.GetName () +" \\ Ncompany: "+ Product.getcompany () +" \\ NPrice: "+ String.Valueof (Product.GetPrice ()));) SetContentView (textView);))
The getSerializable () method is applied to obtain data, since the Product class implements the Serializable interface. Thus, we can transmit one single object instead of a dialing of disparate data.
Hello.
You must pass the data obtained via UART in Activity. This can be done by creating a stream in Activity in which to organize while cycle (! isinterrupted ()) and submit data from the UART buffer. After that, by calling the UI stream of Activity - MainActivity.this.RunonuithRead (New Runnable (), perform the necessary actions with this ACTIVITY. But if we call other ACTIVITY from the main ACTIVITY, then the organized thread does not allow to transmit data to the newly created ACTIVITY. If I Correctly understand, so that the data from the stream can be transferred to any ACTIVITY, the flow must be created not in Activity, but in Service.
QUESTION: UAR has received data, in the stream (which is created in the Service), it is necessary to transfer data to Activity, which is now active, how can this be done and is it done at all?
1 answer
In each ACTIVITY, create Handler. In the OnResume () method, this Activity makes BindService (). There, one of the parameters is Interface ServiceConnection. The implementation of it is at least the same ACTIVITY. Implement in it onserviceConnected (). In this callback, one of the parameters comes to the Service itself. So call the SETHAndler () from this service. Pass the handler there, which is in the current ACTIVITY. And here are the incoming data on the UArt throw in Service on this handler. By the way, Handler traditionally works in the main thread, so it will not be necessary to perform Runonuithread.
The application does not always consist of one screen. For example, we created very useful program And I want to know the user who is its author. He presses the "About Program" button and falls on new screenwhere useful information about the version of the program, the author, the address of the site, how many cats from the author, etc. Perceive the activity screen as a web page with a link to another page. If you look at the code in the file MainActivity.java. From past lessons, you will see that our class MainActivity. also refers to Activity (or his heirs) or, given more precisely, inheritated from him.
Public Class MainActivity Extends AppCompatactivity
As it is easy to guess, we should create a new class, which can be similar to MainActivity. And then somehow switch to it when you press the button.
For the experiment, we will take the program from the first lesson and will use the button for experiments (or create a new project with one button on the screen). Next, create a new form to display. useful information. For example, show the user who makes a cat when goes left and right. Agree it is very important informationgiving the key to the unclelling universe.
Create new activity will be manually, although in the studio there are ready templates. But there is nothing complicated and for better understanding it is useful to make everything with your hands.
Create a new XML markup file activity_about.xml. in folder rES / Layout.. Right-click on the folder layout. and select from the context menu NEW | Layout Resource File.. A dialog box appears. In the first field enter the name of the file activity_about. In the second, you need to enter the root element. Default there stands Constraintlayout.. We wash the text and enter ScrollView.. Input multiple characters is enough for the studio to suggest ready-made options, you can immediately press ENTER, without waiting for the word full input:
It turns out the corresponding billet in which the element will insert TextView..
Information will be removed from resources, namely from a string resource. about_text.. Now it is highlighted in red, signaling about the absence of information. It was possible to click Alt + Enter. And enter text in the dialog box. But for our example, this method will not suit, since our text will be multiplay, using control characters. Therefore, proceed in a different way. Open file. rES / VALUES / STRINGS.XML And enter the following text manually:
We used the simplest HTML-type text formatting tags , , . For our example, it is enough to highlight the fatty words that belong to the cat and the direction of movement. To transfer text to new string Use symbols \\ N.. Add another string resource for the header of the new screen:
Marking figured out. Next you need to create a class for the window Aboutactivity.java.. Select in the menu File | NEW | Java Class. and fill the right fields. At first, it is enough to specify only the name. Then disaster with other fields.
We get the workpiece.
Now the class is almost empty. Add the code manually. Class must be inherited from abstract class Activity or his relatives like FragmentActivity., AppCompatactivity etc. Finish eXTENDS ACTIVITY.. The activity class should have a method onCreate (). We put the mouse cursor inside the class and choose in the menu Code | Override Methods. (Ctrl + O). In the dialog box we are looking for the desired class, you can dial the first characters to quickly search on the keyboard. In the created method, you need to call the method setContentView ()which will load the prepared markup on the screen. We will have this option.
Package ru.AlexanderKlimov.Helloworld; Import Android.app.ActiveIVITY; Import android.os.Bundle; / ** * Created by Alexander Klimov On 01.12.2014. * / Public Class ABOUTACTIVITY EXTENDS ACTIVITY (SAVEDINSTANCESTATE); setContentView (R.Layout.Activity_about);))
Now the most important thing begins. Our task is to go to a new screen when you click the button on the first screen. Go back to class MainActivity.. We write a click click handler:
Public Void OnClick (MainAntivity.this, aboutactivity.class); Startactivity (Intent);)
Here I used a way to handle the button pressing about which was told in the class.
To start a new screen, you need to create a class instance. Intent. and specify the current class in the first parameter, and in the second - the class for the transition, we have it Aboutactivity.. After that, the method is called startActivity ()which launches a new screen.
If you now try to check the operation of the application in the emulator, then you will receive an error message. What did we do wrong? We missed one important step. Need to register new Activity In Manifesto Androidmanifest.xml.. Find this file in your project and click on it twice. A file editing window opens. Add new tag
So the string resource was useful. about_title.. Run the application, click on the button and get a window About the program. So we learned how to create a new window and call it to click the button. And at our disposal a megaudobal program appeared - now there will always be a hint at hand, which makes a cat when goes left.
I look again that the second created class of activity should be inherited from class Activity or him like ( ListActivity. etc.), have an XML markup file (if required) and be registered in the manifest.
After calling the method startActivity () New activity will be launched (in this case Aboutactivity.), it will be visible and moves to the top of the stack containing the working components. When calling a method fINISH () Of the new activity (or when you press the Return Hardware Key), it will be closed and removed from the stack. The developer can also move to the previous (or to any other) activity using the same method startActivity ().
Create a third screen - a way for lazy
Programmers, like cats, are lazy creatures. Constantly remember that for activity you need to create a markup and class that is inherited from Activity, and then do not forget to register the class in the manifesto - yes, nafig.
In this case, select in the menu File | NEW | Activity | Basic Activity (or other template). Further, a familiar window for creating a new activity will appear. Fill the necessary fields.
Click on the button FINISH. And the activity will be ready. To make sure that, open the manifest file and check availability. new recording. I no longer say about the files of the class and markup, they will appear in front of you.
Alone add new button On the main activity screen and write the code for the transition to the created activity.
At first, I would advise you to manually create all the necessary components for the new activity to understand the relationship between the class, markup and manifesto. And when you have a hand, you can use the Activity Creation Wizard to speed up work.
Transmission of data between activities
We used the simplest example To call another screen of activity. Sometimes it is required not only to call a new screen, but also transfer data to it. For example, the username. In this case, you need to use a special area extradata.which is available at class Intent..
Region extradata. - This is a list of couples key / valuewhich is transmitted along with the intention. Lines are used as keys, and for values \u200b\u200byou can use any primitive types of data, primitive arrays, class objects Bundle and etc.
For data transfer to another activity method is used putextra ():
INTENT.PUTEXTRA ("key", "value");
Taking activity should cause some suitable method: getIntextra (), getStringextra () etc.:
Int Count \u003d getIntent (). GetIntextra ("Name", 0);
We remake the previous example. We already have three activity. At the first activity will be placed two text fields and a button. Appearance May be as follows:
In the second activity SECONDACTIVITY. Installation element TextView.where we will display the text obtained from the first activity. We write the following code for the method onCreate () In second activity.
@Override protected void onCreate (Bundle savedInstanceState) (super.onCreate (savedInstanceState); setContentView (R.layout.activity_second); String user \u003d "zhyvotnyh"; String gift \u003d "donut hole"; TextView infoTextView \u003d (TextView) findViewById ( R.ID.TextViewInfo); infotextView.SetText (User + ", you were sent" + Gift);)
If you start the program now and simply call the second window, as described in the first part of the article, we will see the default inscription Yellowed, you passed a hole from the bagel. Agree, it is quite offensive to receive such messages.
I fix the situation. Add code from first activity:
Public void onClick (View view) (EditText userEditText \u003d (EditText) findViewById (R.id.editTextUser); EditText giftEditText \u003d (EditText) findViewById (R.id.editTextGift); Intent intent \u003d new Intent (MainActivity.this, SecondActivity. Class); // In the Username key, you will pihem text from the first text field intent.Putextra ("username", userdittext.gettext (). Tostring ()); // B key Gift Piham text from the second text field Intent.Putextra ("Gift ", giftedittext.gettext (). Tostring ()); startActivity (INTENT);)
We placed in a special object container Intent. Two keys with values \u200b\u200bthat are taken from text fields. When the user enters data into text fields, they will fall into this container and will be transferred to second activity.
The second activity should be ready for a warm reception of the messages as follows (highlighted fat).
// default values \u200b\u200bString User \u003d "Yellow"; String Gift \u003d "hole from the bubble"; user \u003d getintent (). GetExtras (). GetString ("UserName"); Gift \u003d GetIntent (). GetExtras (). GetString ("Gift"); TextView InfotextView \u003d (TextView) FindViewByid (R.ID.TextViewInfo); infotextView.setText (User + ", you were sent" + GIFT);
Now the message does not look like this, but even pleasant for someone. In difficult examples, it is desirable to add a check when processing data. There are situations when you run second activity with empty data type nULLWhat can lead to the collapse of the application.
In our case, we know that we are waiting for a string value, so the code can be rewritten:
INTENT INTENT \u003d GETINTENT (); user \u003d intent.getStringextra ("UserName");
User \u003d getintent (). GetStringextra ("UserName");
The program has a disadvantage - it is not clear from whom we get led. Any well-brought up Mint will not take a gift from an anonymous source. Therefore, as a homework, add another text box to enter the name of the user who sends the message.
Google recommends using the following format for the keys: the name of your package as a prefix, and then the key itself. In this case, you can be confident in the uniqueness of the key when interacting with other applications. Approx like this:
Public Final Static String User \u003d "ru.alexanderklimov.myapp.user";
Who put the cat Vaska - get the result back
It does not always happen to simply convey these other activity. Sometimes you need to get information back from other activity when it is closed. If we used to use the method startatoryIVITY (Intent Intent)then there is a relative method startatoryIFORRESULT (Intent Intent, Int RequestCode). The difference between the methods is additional parameter Requestcode.. In fact, it is just an integer that you can think of yourself. It is necessary in order to distinguish from whom the result came. Suppose you have five additional screens And you assign them values \u200b\u200bfrom 1 to 5, and on this code you can determine whose result you need to process. You can use -1, then it will be equivalent to the method call startActivity (). I will not get any result.
If you use the method startatoryIForResult ()You need to override the method in the code for receiving the result onactivityResult () and process the result. Confused? Let's wonder the example.
Suppose you are a deer. Information was received that two pieces of sausages and other products were stolen from the restaurant from the table of an influential person. Suspusage Palo on three suspects - crow, fucking pussy and cat Vaska.
One of the visitors provided a series of photos from his Powder iPhone:
There is also an indication of another witness: And Vaska listens, yes eats.
Create a new project Sherlock With two activities. On the first screen there will be a button to switch to the second screen and the text label in which the name of the thief will be displayed.
On the second screen there will be a group of switches:
Since we will expect a response from the second screen, we need to use the method startatoryIForResult () On the first screen in which we will give a variable Choose_thief. as a parameter Requestcode..
Static Final Private Into Choose_Thief \u003d 0; Public Void OnClick (View V) (MainActivity.this, ChooseActivity.class); StartactivityForResult (QuestionIntent, Choose_thief);)
Look at the code. When you click on the button, we are going to work with the second screen ChooseActivity. And launch the second screen with the expectation of the result.
Go to the second screen and will write code for second activity.
Public Final Static String thief \u003d "ru.alexanderklimov.sherlock.thief"; Public Void Onradioclick (View V) (Intent Answerintent \u003d New Intent (); Switch (V.Getid ()) (Case R.ID.RADIODOG: ANSWERINTENT.PUTEXTRA (Thief, "fucking pussy"); break; case r.id .radiocrow: Answerintent.Putextra (Thief, "Crow"); Break; Case R.ID.RADIOCAT: ANSWERINTENT.PUTEXTRA (Thief, "Przhevalsky's Horse"); Break; Default: Break;) SetResult (result_ok, answerintent); finish ();)
Here everything is simple when the detective chooses the name of the criminal, then through the method putextra () We pass the key name and its value.
For convenience, after selecting, we immediately close the second window and transmit the value before closing. Result_ok.so that it was clear that the choice is made. If the user closes the screen via the BACK button, then the value will be transmitted Result_canceled..
Method sETRESULT () Takes two parameters: the resulting code and the result itself presented in the form of intention. The resulting code suggests what the result ended the work of activity, as a rule, is either Activity.Result_ok.either Activity.Result_canceled.. In some cases, you need to use your own refund code for processing specific options for your application options. Method sETRESULT () Supports any integer value.
If you transmit data clearly through the button, it would be nice to add a method fINISH ()To close the second activity as unnecessary. If the transition occurs through the back button, it is not necessary to do this.
If the activity was closed by the user when the hardware return button is pressed or if the method is fINISH () was caused earlier than the method sETRESULT ()The resulting code will be installed in Result_canceled., and returning intention will show the value nULL.
Return to the first screen. The first screen awaits a response from the second screen, so you need to add to the code method onactivityResult ().
@Override protected void onActivityResult (int requestCode, int resultCode, Intent data) (super.onActivityResult (requestCode, resultCode, data); TextView infoTextView \u003d (TextView) findViewById (R.id.textViewInfo); if (requestCode \u003d\u003d CHOOSE_THIEF) ( if (resultcode \u003d\u003d result_ok) (String ThiefName \u003d Data.getStringExtra (chooseactivity.thief); infotextView.settext (thiefName);) Else (infotextView.settext ("); // We erase the text)))
The method expects incoming data with the code. Choose_thief.and if such data arrive, then retrieves the value from the key ChooseActivity.thief Using the method getStringextra. The obtained value we derive in TextView. (variable infotextView.). If we returned to the screen via the BACK button, then simply erase the text.
When closing a subsidiary inside the parent component, the handler is triggered onactivityResult (). Handler onactivityResult () Takes several parameters.
- Request code. The code that was used to start activity returning the result
- Result code. The result code set by subsidiary and indicating how its work ended. It can be any integer value, but, as a rule, either Activity.Result_ok.either Activity.Result_canceled.
- Data. The intention used for packing returned data. Depending on the purpose of subsidiary activity, it may include the URI path representing the selected part of the content. Alternatively (or additions), subsidiary can return information in the form of simple values \u200b\u200bpacked in the intent parameter extras.
If the work of subsidiary activity ended unforeseen or if the result code was not specified before closing, this parameter will be equal to Activity.Result_canceled..
Run the project, click on the button and go to the second screen. We choose one of the options. If you select a crows, the screen closes and the name of the criminal will appear on the first screen. If you choose a snack, then its name will appear.
By the way, if you choose a cat, then its name will not appear! Check and see for yourself. You will ask why? Elementary Watson! The criminal did not consider one important detail. The restaurant was observed from the camcorder, and the record showed who actually stole the sausage and substituted the cat. Vaska, hold on!
P.S. If at first it seemed incomprehensible, then much clearer with a lot. Data transmission between screens is often found in the applications and you will not read the example more than once.
P.P.S. Best fish - sausage. Knowing this weakness, it was not difficult to substitute a cat.
Use filters
In the article, I showed a common way to transition to another activity, when in the method startActivity () The current class and class for switching is indicated. By the way, the class of activity does not have to be part of your application. If you know the name of the class from another application, you can go to it. But you can go to another activity in another way.
In practice, meets less often, but can come in handy. Suppose you already have the second activity. In the manifesto add a special filter to it:
And run second activity through a button click in this way.
Public Void ONCLICK (New Intent) (RU.AlexanderKlimov.TestApplication.secondactivity "));)
Replace long string On the constant.
Public Static Final String Action_second_activity \u003d "ru.alexanderklimov.TestApplication.secondactivity"; Public Void OnClick (New Intent (Action_second_Activity);)
So what we did. For the second activity, we prescribed the filter and indicated the name for action. In attribute android: Name.. For convenience, I simply placed the full name of activity with the name of the package. Class Designer Intent. It has several overloaded versions. In one of the versions, you can specify a string for action. We indicated our created action, which is written in the second activity. The system while working browsing the manifests of all installed applications. When searching for compliance, the system finds our filter and starts the desired activity.
By the same principle, other activities can be launched. Look at the example. If you copy an example to yourself and look at the documentation for android.Provider.Settings.Action_airplane_Mode_Settings.You will see that a string constant corresponds to this code. public Static Final Java.Lang.String Action_airplane_Mode_Settings \u003d "Android.settings.airplane_Mode_Settings". Compare with our code. You may assume that the activity of settings for autonomous regime This string is prescribed in the filter.
Filter category name android.intent.category.default. Says the system that the default action should be performed, namely, run activity. There are other names that are not interested in us.
And now the question is on the backfill. What happens if you create another activity and specify the same filter as the second activity? And let's check. Create third activity and copy the block with a filter from the second activity into it.
Click on the button in the first activity. The system will ask you to choose the desired option.
If you select Always, the next time you do not have to choose. To reset the selection, go to the properties of the application in the settings and locate the button. Clear Defaults..
Running activity by his name
In the designer Intent. The second parameter is class. But suppose that there is some kind of database, where the names of the activities are indicated and we need to run the necessary activity by its name. We can on the basis of a string variable to get the class itself and run activity.
Try (// Full name of the class of activity String ActivityName \u003d "ru.alexanderklimov.testapplication.secondactivity"; // Receive the Class Class object> MyClass \u003d Class.Forname (ActivityName); INTENT INTENT \u003d NEW INTENT (THIS, MYCLASS); StartActivity (INTENT); ) CATCH (ClassNotFoundException E) (E.PrintStackTrace ();)