There are five interaction modes: interaction through broadcast, interaction through shared files, interaction through Messenger, interaction through custom interfaces, and interaction through AIDL. (Maybe more) The difference between Service and Thread Thread: Thread is the smallest unit of program execution, and Thread can be used to perform some asynchronous operations. Service: Service is a mechanism of Android. When it is running, if it is a Local Service, then the corresponding Service is running on the main thread of the main process. If it is a Remote Service, then the corresponding Service is running on the main thread of an independent process. Threads run independently, which means that when an Activity is finished, if the Thread is not stopped or the run method in the Thread is not completed, the Thread will continue to run. Therefore, there is a problem: when the Activity is finished, the reference to the Thread is no longer held, which means that the Thread can no longer be controlled. On the other hand, there is no way to control the same Thread in different Activities. For example, if a Thread needs to connect to a server to verify data at regular intervals, the Thread needs to run in the background all the time. If the Activity that created the Thread is terminated but the Thread is not stopped, there will be no way to control the Thread unless the program process is killed. At this time, if you create and start a Service, create, run and control the Thread in the Service, this will solve the problem (because any Activity can control the same Service, and the system will only create one instance of the corresponding Service). Therefore, you can think of Service as a message service. You can call Context.startService, Context.stopService, Context.bindService, Context.unbindService anywhere there is a Context to control it. You can also register BroadcastReceiver in Service and achieve control by sending broadcasts. These are things that Thread cannot do. Service Lifecycle 1. The life cycle of the started service (startService()). If a Service is started by an Activity calling the Context.startService() method, then the Service will run in the background regardless of whether there is an Activity using bindService() to bind or unbindService() to unbind the Service. If a Service is started multiple times, its onCreate() method will only be called once, which means that only one instance of the Service will be created, and its onStartCommand() will be called multiple times (corresponding to the number of times startService() is called). The Service will continue to run in the background until stopService() is called, or its own stopSelf method is called. Of course, if system resources are insufficient, the system may also end the service. 2. The life cycle of the bound service (bindService()). If a Service is bound and started by calling the Context.bindService() method, no matter how many times bindService() is called, the onCreate() method will only be called once, and the onStartCommand() method will never be called. At this time, the onBind() method will be called. Once the connection is established, the Service will continue to run unless Context.unbindService() is called to disconnect or the Context that previously called bindService() no longer exists (such as the Activity is finished), the system will automatically stop the Service and the corresponding onDestroy() will be called. 3. The life cycle of a service that is started and bound. If a Service is started and bound again, it will always run in the background. Calling unbindService() will not stop the Service, but you must call stopService() or the Service's stopSelf() method to stop the Service. 4. Clear the service when it is stopped. When a Service is terminated, the Service's onDestroy() method will be called, where some cleanup work should be done, such as stopping the threads created and running in the Service. Process life cycle When the Service runs in a low-memory environment, the system will kill some processes. Therefore, the priority of the process will be very important: 1. If the Service is currently executing onCreate(), onStartCommand(), or onDestroy(), the main process will become the foreground process to ensure that the code can be executed to completion and avoid being killed. 2. If the Service is already started, the main process will be less important than other visible processes, but more important than other invisible processes. Visible here means that visible processes always have the highest priority for users, and users are the top priority. However, only a small number of processes are always visible to users, so unless the system is extremely low on memory, the service will not be killed. 3. If there is a client connected to the Service, then the Service is always more important than the Client. 4. Service can use startForeground() to put the Service in the foreground state. This will reduce the chance of being killed when the memory is low, but if the memory is extremely low, the Service will still be killed in theory. But this situation is basically not considered. Broadcast Interaction When it comes to the interaction between Activity and Service, many people may think of BroadCast first. In Android, broadcasting is a good way of interaction provided by the system. For example, when the battery is too low or the boot is completed, the system will send out corresponding system broadcasts. Our application only needs to register the corresponding broadcast receiver to receive these system broadcasts. At the same time, we can also define our own broadcasts, so that different Activities, Services and applications can interact through broadcasts. We analyze the interaction between Service and Activity by simulating the background download of the application. When we click the StartService button, the progress bar on the interface will increase by 1 every second. Because it is a simulated download, we use a Timer in the Service to implement the download action. In the Timer, an integer data i is incremented (i++), and then the Client obtains the i value on the Server and displays it on the interface, thus achieving the purpose of simulation. 1.1. Implementation Principle The server sends the current download progress by broadcasting. The client registers a listener for this broadcast. After receiving the broadcast, it parses the current download progress in the broadcast and updates it to the interface. 1.2. Implementation steps 1.2.1 Start the Service through startService() in the Client.
Here mIntent = new Intent(); the Process.myPid() method can get the ID number of the current process. 1.2.2 After receiving the start command, DownLoadService executes the onCreate() method and starts a timer to count the simulated download.
The intent here is used by the server to transmit data to the client. The action used is "com.seven.broadcast". The client can only receive the server's broadcast and parse the content if it has registered the corresponding action. Process.myPid() is used to obtain the ID of the current process. 1.2.3 The timer on the Server side counts and sends a broadcast to inform the Client side of the current download progress.
Set the value of intent through intent.putExtra(key,value), and then send the broadcast through the sendBroadcast(intent) method. 1.2.4 On the client side, instantiate BroadcastReceiver through an anonymous inner class and override the onReceive() method.
In the onReceive() method, determine whether it is a broadcast sent by the server. If it is, unpack the intent data carried in the broadcast. You can also write a separate class that inherits from BroadcastReceiver, override the onReceive() method in it, and instantiate its object in the client, which can also achieve the corresponding effect. This can be used to implement static registration broadcasts later. 1.2.5 Updated the download progress on the main interface.
Here, the obtained progress is judged once. If the obtained value is normal, it will be displayed on the interface and the progress of the progress bar will be updated. If it is abnormal, it will be returned. 1.2.6 You must register and unregister the broadcast. You can only receive the corresponding broadcast after registering. There are two ways to register. Dynamic registration/unregistration:
Dynamic registration can be registered at any time and canceled at any time. Static registration:
Note: MyBroadcastReceiver here is a class that inherits from BroadcastReceiver. Static registration is only required once, so the broadcast will always be valid as long as the program is not uninstalled. Finally, post the entire AndroidManifest.xml file
Here, android:process = ":remote" allows the Service to run in a separate process, thus simulating cross-process communication. 1.3 Summary The interactive operation between Activity and Service through broadcast is simple and easy to implement, and it can be used for simple applications. However, the disadvantages are also obvious. Sending broadcasts is restricted by the system. The system will give priority to sending system-level broadcasts. In certain specific cases, our customized broadcasts may be delayed. At the same time, long-time operations cannot be processed in the broadcast receiver, otherwise the system will display ANR, that is, the application is unresponsive. #p# Shared file interaction 2The shared file mentioned here means that the Activity and Service use the same file to transfer data. We use SharedPreferences to achieve sharing, and of course other IO methods can also be used to achieve it. When implementing interaction in this way, it should be noted that when reading and writing files, only one party can read and the other party can write at the same time, and both parties cannot write at the same time. 2.1 Implementation Principle The server writes the current download progress into the shared file, and the client reads the download progress in the shared file and updates it on the main interface. 2.2 Implementation steps 2.2.1 Start the Service via startService() on the Client side.
2.2.2 After receiving the startup intent, the server executes the onCreate() method, starts the timer, simulates the download, and initializes the SharedPreferences object preferences.
2.2.3 Start counting and write the download progress to the XML file in the shared_prefs folder. The content is saved in the form of key-value pairs.
There are a few things to note when using SharedPreferences: First, you need to get a file reference before using sharedPreferences.
Secondly, use sharedpreferences to write data.
Finally, the way to read the data.
2.2.4 The client reads the XML file in the /data/data/com.seven.servicetestdemo/shared_prefs folder and obtains the key-value pairs in it to obtain the current download progress and update it to the main interface.
2.3 Summary Because the method is simple, I won't post the AndroidManifest.xml file. This method is very convenient for implementing the interaction between Activity and Service, just like using a pipe, one writes in and the other reads out. But this method also has its flaws. When the written data is complex or the amount of data is large, it may cause inconsistency errors between the written and read data. At the same time, because it passes through a transfer station, this operation will be more time-consuming. #p# Messenger Interaction 3Messenger means messenger, which refers to a Handler object, and others can send messages to it (using the mMessenger.send(Message msg) method). This class allows cross-process communication based on Message. On the server side, a Messenger is created using Handler. The client can communicate with the server as long as it obtains the Messenger object on the server side. In other words, we can use Messenger as a microphone between the client and the server, so that we can communicate. 3.1 Implementation Principle Messages are transmitted between the Server and the Client through a Messenger object, which is similar to an information transfer station and carries all information. 3.2 General usage of Messenger (1). Create a messenger object on the server side. mMessenger = new Messenger(mHandler) (2). The client uses bindService() to bind to the server. (3). The onBind() method on the server side returns a binder object. return mMessenger.getBinder(); (4). The client uses the returned binder object to get the server messenger.
It is found that its mTarget is obtained through AIDL, which is actually the one created remotely. (5). The client can use the server's messenger object to send messages to the server. rMessenger.send(msg); In this way, the Handler object on the server side can receive the message, and then process it in its handlerMessage(Message msg) method. After these five steps, only the client side sends messages to the server side. Such message transmission is one-way, so how to achieve two-way message transmission? First, you need to make changes in step 5. Before send(msg), set the client's own messenger to the message through msm.replyTo = mMessenger. In this way, when the server receives the message, it also gets the client's messenger object. Then the server can also use the obtained client's messenger object to send messages to the client. cMessenger = msg.replyTo2 cMessenger.send(message); This completes the function of sending messages from the Server to the Client, so that the Client can receive the message sent by the server in the handlerMessage() method of its own Handler object for processing. 3.3 Implementation steps 3.3.1 Create and initialize the server-side messenger object.
3.3.2 Use the bindService() method on the Client to bind the Server.
3.3.3 Return a binder object in the onBind() method on the server side.
Here, mMessenger is the messenger object on the server side. 3.3.4 The client uses the ServiceConnected() method to obtain the messenger object on the server.
While obtaining the messenger object on the server side, the client side's own messenger object is also initialized, and a message is sent to the server side through the sendMessage() method, indicating that the download can begin. 3.3.5 The client uses the obtained rMessenger to send a message to the server, and encapsulates the client's messenger into the message and sends it to the server.
Here, MessengerService.TEST is a static constant in the server. Msg.replyTo = mMessenger; it means that the message sent to the server carries the messenger of the client. 3.3.6 The Server receives the message sent by the Client and obtains the Client's messenger object.
After receiving the information from the Client, the Server starts a timer to simulate the download and receives the messenger object from the Client. 3.3.7 The Server sends data to the Client.
Directly use the received client messenger object to send the current download progress to the client. 3.3.8 The Client receives data from the Server.
The reception on the client side is very similar to that on the server side. After receiving the data from the server side, the interface is updated and the download progress is updated. Here is the AndroidManifest.xml file:
Here, a filtering action is added to the Service registration, and only the matching action can start the corresponding Service. 3.4 Summary The interaction between Activity and Service is realized through Messenger. If we go a little deeper, we can know that Messenger is also realized through AIDL. For the first two implementation methods, the Messenger method is generally easier to understand, which is the same as the usual communication between Handler and Thread. #p# Custom interface interaction 4What is a custom interface? In fact, it means that we achieve the purpose of interaction between Activity and Service through the implementation of the interface. We achieve the purpose of data interaction by building a bridge between Activity and Service, and this implementation method is very similar to AIDL (which will be discussed later). 4.1 Implementation Principle Customize an interface with an empty method for getting the current download progress. The server uses a class that inherits from Binder and implements the interface, overriding the method for getting the current download progress. The client obtains the object of this class through ServiceConnection, and can use the method for getting the current download progress, ultimately achieving real-time interaction. 4.2 Implementation steps 4.2.1 Create a new Interface and create an empty method getCurrentLoad() in it to get the current download progress
4.2.2 Create a new server-side DownService to implement ICountService and inherit from Binder through an inner class ServiceBinder and implement the ICoutService interface.
On the server side, implement the empty method getCurrentLoad() to get the download progress; this is automatically generated by Eclipse, and the focus is not here. We need to override the getCurrentLoad() method in the ServiceBinder class, where we return the current download progress i. 4.2.3 The Client uses bindService() to bind to the Server.
When the client is bound to the server, it will delay 1s to get the download progress. The string com.seven.test must be consistent with that declared in AndroidManifest.xml. 4.2.4 The server returns the binder object.
The serviceBinder here inherits Binder and is therefore also a Binder object. 4.2.5 The client obtains the binder object of the server through ServiceConnection.
The acquisition process is completed in the bindService() process, where iCountService is an object of the interface ICountService, which is instantiated here. 4.2.6 After the binding is completed, the server will start downloading. In actual situations, the server will start an independent thread for downloading, which is replaced by i++ here.
After the bindService() method is executed, the onCreate() method in DownLoadService will be called, and the timer will be started in its onCreate() method to make i++. 4.2.7 If the server has started downloading, the client needs to obtain the download progress in time and update it on the main interface.
The client-side Timer starts to obtain the download progress 1 second after bindService() is completed. The method of obtaining the download progress is directly through int curLoad = iCountService.getCurrentLoad(); the getCurrentLoad() method here is a method in the ServiceBinder inner class of DownLoadService. The client-side updates the obtained download progress to the interface and updates the progress bar. 4.3 Summary From the above examples, we can know that this method is simple, practical and highly extensible, but it also has some disadvantages, such as the need to delay some time before starting to obtain the data on the server, so it is impossible to completely synchronize and update from scratch. In summary, the method of implementing the interaction between Activity and Service through a custom interface is still quite practical. It is suitable for communication within the same process, not for cross-process communication. #p# AIDL Interaction AIDL is the abbreviation of Android Interface Definition Language. When mentioning AIDL, we have to talk about Android services. Android supports two types of services: local services and remote services. Local services cannot be accessed by other applications running on the device, that is, they can only be called from within the application, such as download services in some applications, which can only be called from within. For remote services, in addition to being called by the application itself, other applications can also access them. Remote services are generally implemented through AIDL, which allows inter-process communication. This type of service is also called a remote service. There are some important differences between local services and remote services. Specifically, if the service is used entirely by components in the same process (running background tasks), the client starts the service by calling Context.startService(). This type of service is a local service, and its general purpose is to perform long-running operations in the background. Remote services are generally started through the bindService() method, mainly for communication between different processes. We also call remote services AIDL-supported services because clients use AIDL to communicate with services. There are many names for remote services in Android: remote services, AIDL services, external services, and RPC services. 5.1 AIDL implementation flow chart This belongs to the proxy/stub structure. Through this AIDL flowchart, it is easy to find that Android implements IPC by adding a proxy/stub structure to the original C/S framework. For example, you go to an ATM to withdraw money. Then you are the client, and the ATM is your proxy; you don't care where the money is, you just want to take your money out of the ATM. The operations between you and the bank are all implemented by the ATM proxy. Your withdrawal request is transmitted to the other side, the bank's server, through the ATM. It doesn't need to know where you are withdrawing money. What it cares about is your identity and how much money you withdraw. When it confirms your authority, it will perform the corresponding operation and return the operation result to the ATM. The ATM will take out the corresponding amount of money from the safe according to the result returned by the server. After you take out the card, the operation is completed. The ATM is not directly connected to the server. There is a "stub" between them. The ATM communicates with the stub, and the server communicates with the stub. In a sense, the stub is the proxy of the server. 6 5.3 Implementation Principle 7 AIDL is an IPC mechanism of Android, which is often used for cross-process communication. Its main implementation principle is based on the underlying Binder mechanism. 5.4 Implementation steps 5.4.1 Create a project. Create AIDLServer and AIDLClient. There is only one service program in AIDLServer, without a main interface, and its main function is to download. AIDLClient obtains the current download progress from AIDLServer (Note: AIDLServer and AIDLClient are two different APKs. When simulating this example, you need to install the APK compiled by AIDLServer on the simulator first. The installation method can be run directly on the simulator once, and can be installed through adb install your.apk). A new ICountService.aidl file is created on the AIDLServer side. The contents of the file are as follows:
The writing standards of aidl files are as follows: (1) Android supports String and CharSequence (as well as Java's basic data types); (2). If you need to use other AIDL interface types in AIDL, you need to import them, even if they are in the same package structure; (3). Android allows passing classes that implement the Parcelable interface, which requires import; (4) Android supports collection interface types List and Map, but there are some restrictions. The elements must be basic types or the first three types. You do not need to import the collection interface class, but you need to import the types involved in the elements. (5) Non-basic data types, which are not String and CharSequence types, need to have a direction indication, including in, out, and inout. In means it is set by the client, out means it is set by the server, and inout means it can be set by both. 11 The AIDL client needs to copy the ICountService.aidl file of the AIDL server. For convenience, a new package with the same name as the server is created and ICountService.aidl is placed in it. 5.4.2 After we create the ICoutService.aidl file on the server side, Eclipse will automatically generate the ICountService.java file in the /gen/com.seven.aidlserver/ directory. This file is automatically generated by Eclipse, so please do not modify it at will. The content we need to reference later is as follows:
5.4.3 On the server side, create an inner class that inherits from ICountService.Stub and override the getCount() method, and instantiate an object serviceBinder of this class.
This is very similar to the "interaction through interfaces" mentioned earlier. 5.4.4 In the onBind() method on the Server side, return the previous serviceBinder object.
5.4.5 In the onCreate() method of the Server, start the timer to simulate downloading. When the Client binds the Server through bindService(), the onCreate() method of the Server will be executed first.
5.4.6 The Client binds to the Server through bindService().
Here, intent = new Intent("com.seven.aidlserver"); this should be consistent with the filtering when registering the Service on the Server side, that is, the Service will only be started if the same action is issued. At the same time, a timer is started to obtain the download progress. 5.4.7 The client obtains the binder object of the server through ServiceConnection.
The iCountService object here is actually the ICountService object instantiated here. 5.4.8 Get the current download progress and update it on the interface.
By updating the progress bar on the interface, you can easily check the current download progress. Because AIDLServer is just a service inherited from Service, its AndroidManifest.xml file is not posted here. 5.5 Summary AIDL is a common way of inter-process communication in Android. It may be more complicated to use, but it is efficient and has good scalability. At the same time, many system services communicate with applications in this way. Link to this article: http://www.cnblogs.com/yydcdut/p/3961545.html |
<<: Detailed description of the INotifyPropertyChanged interface
>>: Gartner: 75% of apps will fail standard security tests next year
What exactly is “resonance”? Why do some articles...
In the Internet TV industry, terminal manufacture...
Mountains cannot stop you; the sea can also be cr...
On October 8, Lu Han announced his relationship w...
In recent months, the development of Android 13 h...
For many years, I always thought that I possessed...
Source: China Device Evaluation...
【Mobile software: Bo Ke Yuan】 Observations with t...
Judging from various indications, social e-commer...
Do you also want to experience the feeling of hav...
If you want to buy a mobile phone now, you will f...
Quick Facts 1. Summary of mobile phone vertical s...
Today is the 55th World Telecommunication Day. In...
When everyone first discovers that they are nears...
As an important platform for short videos, Douyin...