Service Service Development and Understanding in android
Records of 2017/3/13
Service Services of Four Components
Services do not run in a separate process, but depend on the application process in which they are created.Service: It is a solution to realize the background running of the program in android. It is well suited for tasks that do not require long-term user interaction.
And in fact, services do not automatically open threads. All service codes run on the main thread, so we need to create sub-threads manually.
Inheritance: Implement the runable interface directly or inherit the Thread parent class (in the subthread run method) to start the start() thread.
Inheritance mode: New MyThread().start(); Implementation interface method: new Thread(MyThread).start();
Like many UI libraries. android's UI library is also thread insecure, so you want to update UI elements in your application.
It must be done in the main thread, otherwise an exception will occur.
Let's write a small example to see.
activity_main <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.ldp.com.androidthreadtest.MainActivity"> <Button android:id="@+id/change_text" android:text="Change Text" android:textAllCaps="true" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/text" android:layout_centerInParent="true" android:textSize="20sp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /> </RelativeLayout>
MainActivity package com.example.ldp.com.androidthreadtest; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private TextView text; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); text = (TextView)findViewById(R.id.text); Button button = (Button)findViewById(R.id.change_text); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { text.setText("Nice to meet you"); } }).start(); } }); } }
Design sketch:

It can be solved by updating UI with the usage of asynchronous message processing in android.
Change the code: MainActivity
package com.example.ldp.com.androidthreadtest; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MainActivity extends AppCompatActivity { public static final int UPDATE_TEXT=1; private TextView text; private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ //In this way, multiple asynchronous messages can be implemented to update the UI. case UPDATE_TEXT: text.setText("Nice to meet you"); break; default: break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); text = (TextView)findViewById(R.id.text); Button button = (Button)findViewById(R.id.change_text); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { //Call with Message Object Message message = new Message(); message.what = UPDATE_TEXT; handler.sendMessage(message); } }).start(); } }); } }
If you run it again, you will see that UI operations are not performed in the sub-threads, but only a Message object is created.
Pass this object to handle and handle it with handleMessage(), which in this case allows the operation to run in the main thread rather than in the sub-thread.
Resolve the asynchronous message mechanism:
It is divided into four parts: Message, Handle, MessafeQueue, Looper
Message: Used to pass messages between threads or to send shaping data
handler: Processor for sending and processing messages. sendMessage() handleMessage()
MessageQueue: Message queue in which messages sent by Handler are stored will always exist, and there will only be one MessageQueue object per thread.
Looper: is the steward of MessageQueue in each thread. After calling the loop() method, it will go into the wireless loops to find messages and find the handleMessage(), and there will only be one Looper object in each thread.
Design sketch:

AsyncTask, another tool provided in android, can be learned if the above steps are troublesome.
Of course, the steps are much simpler.
Basic and Usage of Services:
A new service service class can be created directly on the project. We need to inherit the service class and implement several methods.
Note: Services need to be registered in AndroidManifast.xml
For example, create a new MyService class and modify it on the last asynchronous messaging mechanism project
package com.example.ldp.com.androidthreadtest; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.util.Log; public class MyService extends Service { public MyService() { } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } @Override public void onCreate() { super.onCreate(); Log.d("MyService","OnCreat Method Start"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("MyService","onStartCommand Method Start"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); Log.d("MyService","onDestroy Method Start"); } }
activity_main <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/change_text" android:text="Change Text" android:textAllCaps="false" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/start_service" android:text="Start Service" android:textAllCaps="false" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/stop_service" android:text="Stop Service" android:textAllCaps="false" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/text" android:layout_centerInParent="false" android:textSize="20sp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /> </LinearLayout>
MainActivity.java package com.example.ldp.com.androidthreadtest; import android.content.Intent; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MainActivity extends AppCompatActivity implements View.OnClickListener{ public static final int UPDATE_TEXT=1; private TextView text; private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ //In this way, multiple asynchronous messages can be implemented to update the UI. case UPDATE_TEXT: text.setText("Nice to meet you"); break; default: break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); text = (TextView)findViewById(R.id.text); Button button = (Button)findViewById(R.id.change_text); Button startButton = (Button)findViewById(R.id.start_service); Button stopButton = (Button)findViewById(R.id.stop_service); startButton.setOnClickListener(this); stopButton.setOnClickListener(this); button.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.change_text: new Thread(new Runnable() { @Override public void run() { //Call with Message Object Message message = new Message(); message.what = UPDATE_TEXT; handler.sendMessage(message); } }).start(); break; case R.id.start_service: Intent startIntent = new Intent(this,MyService.class); startService(startIntent); break; case R.id.stop_service: Intent stopIntrnt = new Intent(this,MyService.class); stopService(stopIntrnt); break; default: break; } } }
The rendering shows that the oncreat e method and onStartCommand method are executed by clicking on startService, but only the onStartCommand method is executed by clicking several times.
Click Stop to Execute onDestory Method
Design sketch:

Has it been found that we notify the service through activities that can be performed? There is no use for activity.
Service life cycle
Design sketch:

For example, weather software, when used, will display the weather status in the status bar, which is an application of the front desk service.
Modified example in the previous example: MyService
@Override public void onCreate() { super.onCreate(); Log.d("MyService","OnCreat Method Start"); Intent intent = new Intent(this,MainActivity.class); PendingIntent pi = PendingIntent.getActivity(this,0,intent,0); Notification notification = new NotificationCompat.Builder(this) .setContentTitle("This is content title").setContentText("This is content ") .setWhen(System.currentTimeMillis()).setSmallIcon(R.mipmap.ic_launcher) .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher)) .setContentIntent(pi).build(); startForeground(1,notification); }
Design sketch:

Note that if a large number of logical code processing is written in the service, it is likely that ANR(Application Not Response) will occur in the application.
So a standard service should be written as MyService
@Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d("MyService","onStartCommand Method Start"); new Thread(new Runnable() { @Override public void run() { //Concrete logic realization stopSelf();//The purpose of stopping service here is to avoid running all the time. It can also be written as stopService(). } }).start(); return super.onStartCommand(intent, flags, startId); }
In the beginning process, it is often forgotten to open the thread or call the stop service, which causes the program to have problems, so it is provided in android.
IntentService parent class
package com.example.ldp.com.androidthreadtest; import android.app.IntentService; import android.content.Intent; import android.util.Log; /** * Created by Administrator on 2017/3/13. */ public class MyIntentService extends IntentService { public MyIntentService(){ super("MyIntentService");//Call the constructor of the parent class } @Override protected void onHandleIntent(Intent intent) { //Implementing logic without worrying about ARN Log.d("MyIntentService","Thread is "+Thread.currentThread().getId()); } @Override public void onDestroy() { super.onDestroy(); Log.d("MyIntentService","OnDestory Method"); } }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/change_text"
android:text="Change Text"
android:textAllCaps="false"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/start_service"
android:text="Start Service"
android:textAllCaps="false"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/
stop_service" android:text="Stop Service" android:textAllCaps="false" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/myintent_service_start" android:text="Start MyIntent Service" android:textAllCaps="false" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/text" android:layout_centerInParent="false" android:textSize="20sp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /> </LinearLayout>
Register services in AndroidManfest.xml
<service android:name=".MyService" android:enabled="true" android:exported="true"> </service> <service android:name=".MyIntentService"/>
MyService.java remains unchanged
MainActivity.java package com.example.ldp.com.androidthreadtest; import android.content.Intent; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MainActivity extends AppCompatActivity implements View.OnClickListener{ public static final int UPDATE_TEXT=1; private TextView text; private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ //In this way, multiple asynchronous messages can be implemented to update the UI. case UPDATE_TEXT: text.setText("Nice to meet you"); break; default: break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); text = (TextView)findViewById(R.id.text); Button button = (Button)findViewById(R.id.change_text); Button startButton = (Button)findViewById(R.id.start_service); Button stopButton = (Button)findViewById(R.id.stop_service); Button myintetnbutton = (Button)findViewById(R.id.myintent_service_start); myintetnbutton.setOnClickListener(this); startButton.setOnClickListener(this); stopButton.setOnClickListener(this); button.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.change_text: new Thread(new Runnable() { @Override public void run() { //Call with Message Object Message message = new Message(); message.what = UPDATE_TEXT; handler.sendMessage(message); } }).start(); break; case R.id.start_service: Intent startIntent = new Intent(this,MyService.class); startService(startIntent); break; case R.id.stop_service: Intent stopIntrnt = new Intent(this,MyService.class); stopService(stopIntrnt); break; case R.id.myintent_service_start: Log.d("MainActivity","Thread is "+Thread.currentThread().getId()); Intent intentService = new Intent(this,MyIntentService.class); startService(intentService); break; default: break; } } }
Design sketch:

Let's do an example of what we learned before a collection: