4.2.2 Advanced Service
Category Android Basic Tutorial
Introduction to This Section
>
In the previous section, we learned about the lifecycle of Service and the two methods to start a Service. This section continues to delve into IntentService in Service, and demonstrates the implementation of foreground services and polling!
1. Usage of IntentService
After the last section, we already know how to define and start a Service. However, if we directly place a time-consuming thread in the onStart() method of Service, although it can be done, it is likely to cause an ANR exception (Application Not Responding). Android's official documentation on Service includes the following statement:
Direct Translation:
>
- Service is not a separate process; it runs in the same process as its application.
Therefore, Android provides us with an alternative to solve the above problem, which is the IntentService we are going to discuss next. IntentService is a class that inherits from Service and handles asynchronous requests. It has a worker thread to handle time-consuming operations, and the request Intents are queued.
Workflow:
>
The client starts IntentService by calling startService(Intent); We do not need to manually control IntentService, as it will stop automatically when the task is completed; IntentService can be started multiple times, and each time-consuming operation will be executed in the onHandleIntent callback method of IntentService in a queue manner, and only one worker thread will be executed at a time, finishing one before moving on to the next!
Next is the code demonstration. Most online examples compare Service with IntentService by defining a long sleep time to demonstrate the ANR exception of Service, and then introduce how good IntentService is! Here, we will not demonstrate Service. Online examples are mostly custom Services, and then Thread.sleep(20000) in the onStart() method to cause an ANR exception. If interested, you can write the code yourself. Here, we will only demonstrate the usage of IntentService!
TestService3.java
public class TestService3 extends IntentService {
private final String TAG = "hehe";
// Must implement the constructor of the parent class
public TestService3()
{
super("TestService3");
}
// Must override the core method
@Override
protected void onHandleIntent(Intent intent) {
// Intent is sent from Activity, carrying identification parameters, performing different tasks based on parameters
String action = intent.getExtras().getString("param");
if(action.equals("s1")) Log.i(TAG, "Starting service1");
else if(action.equals("s2")) Log.i(TAG, "Starting service2");
else if(action.equals("s3")) Log.i(TAG, "Starting service3");
// Let the service sleep for 2 seconds
try {
Thread.sleep(2000);
} catch(InterruptedException e) { e.printStackTrace(); }
}
// Override other methods to view the sequence of method calls
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind");
return super.onBind(intent);
}
@Override
public void onCreate() {
Log.i(TAG, "onCreate");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void setIntentRedelivery(boolean enabled) {
super.setIntentRedelivery(enabled);
Log.i(TAG, "setIntentRedelivery");
}
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy");
super.onDestroy();
}
}
Register Service in AndroidManifest.xml
<service android:name=".TestService3" android:exported="false">
<intent-filter >
<action android:name="com.test.intentservice"/>
</intent-filter>
</service>
Start the service three times in MainActivity:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent it1 = new Intent("com.test.intentservice");
Bundle b1 = new Bundle();
b1.putString("param", "s1");
it1.putExtras(b1);
Intent it2 = new Intent("com.test.intentservice");
Bundle b2 = new Bundle();
b2.putString("param", "s2");
it2.putExtras(b2);
Intent it3 = new Intent("com.test.intentservice");
Bundle b3 = new Bundle();
b3.putString("param", "s3");
it3.putExtras(b3);
// Start IntentService multiple times, each time a new worker thread is created
// but there is only one instance of IntentService
startService(it1);
startService(it2);
startService(it3);
}
}
Summary:
>
When a background task needs to be divided into several sub-tasks and executed in order, i.e., asynchronous operations, if we still define a normal Service and then create threads in the onStart method and need to control the threads, it becomes very cumbersome. In this case, we should customize an IntentService and complete the related tasks in the onHandleIntent() method!
2. Communication Between Activity and Service
So far, we have been starting and stopping the Service through the Activity. Suppose we are starting a background download Service, and we want to know the progress of the download tasks in the Service! This requires communication between the Service and the Activity, and the medium for this communication is the onBind() method in the Service! Returning a custom Binder object!
The basic process is as follows:
- In the custom Service, define a custom Binder class, and then expose the methods that need to be accessed in this class!
- In the Service class, instantiate this custom Binder class, and then override the onBind() method to return this Binder object!
- In the Activity class, instantiate a ServiceConnection object, override the onServiceConnected() method, then obtain the Binder object, and call the relevant methods!
3. Implementation of a Simple Foreground Service
By now, we know that Service usually runs in the background, but the system priority of Service is still relatively low. When the system memory is insufficient, it may recycle the Service running in the background. In this case, we can use a foreground service to make the Service slightly less likely to be killed by the system, although it may still be killed... A foreground service is a Notification displayed in the status bar.
The implementation is also very simple. The project I recently worked on just used this foreground service, so I extracted the core code and shared it:
In the custom Service class, override the onCreate(), and then customize the Notification according to your needs; after customization, call startForeground(1, notification object) to enable the foreground service! Core code as follows:
public void onCreate()
{
super.onCreate();
Notification.Builder localBuilder = new Notification.Builder(this);
localBuilder.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0));
localBuilder.setAutoCancel(false);
localBuilder.setSmallIcon(R.mipmap.ic_cow_icon);
localBuilder.setTicker("Foreground Service Start");
localBuilder.setContentTitle("Socket Server");
localBuilder.setContentText("Running...");
startForeground(1, localBuilder.build());
}
startForeground(1, localBuilder.getNotification());
}
Screenshot of the running effect:
- 2.3.6 ToggleButton and Switch
- 2.3.7 ProgressBar (Progress Bar)
- 2.3.8 SeekBar (Drag Bar)
- 2.3.9 RatingBar (Star Rating Bar)
- 2.4.1 ScrollView (Scroll Bar)
- 2.4.2 Date & Time Components (Part 1)
- 2.4.3 Date & Time Components (Part 2)
- 2.4.4 Adapter Basics
- 2.4.5 Simple Usage of ListView
- 2.4.6 BaseAdapter Optimization
- 2.4.7 ListView Focus Issues
- 2.4.8 Solving Checkbox Misalignment in ListView
- 2.4.9 Data Update Issues in ListView
- 2.5.0 Building a Reusable Custom BaseAdapter
- 2.5.1 Implementing Multiple Item Layouts in ListView
- 2.5.2 Basic Usage of GridView (Grid View)
- 2.5.3 Basic Usage of Spinner (List Option Box)
- 2.5.4 Basic Usage of AutoCompleteTextView (Auto-complete Text Box)
- 2.5.5 Basic Usage of ExpandableListView (Collapsible List)
- 2.5.6 Basic Usage of ViewFlipper (Flip View)
- 2.5.7 Basic Usage of Toast
- 2.5.8 Detailed Explanation of Notification (Status Bar Notification)
- 2.5.9 Detailed Explanation of AlertDialog (Dialog Box)
- 2.6.0 Basic Usage of Several Common Dialogs
- 2.6.1 Basic Usage of PopupWindow (Floating Box)
- 2.6.2 Menu (Menu)
- 2.6.3 Simple Usage of ViewPager
- 2.6.4 Simple Usage of DrawerLayout (Official Side Sliding Menu)
- 3.1.1 Event Handling Mechanism Based on Listeners
- 3.2 Event Handling Mechanism Based on Callbacks
- 3.3 Analysis of Handler Message Passing Mechanism
- 3.4 TouchListener vs OnTouchEvent + Multi-touch
- 3.5 Listening for Content Changes in EditText
- 3.6 Responding to System Setting Events (Configuration Class)
- 3.7 AsyncTask Asynchronous Task
- 3.8 Gestures (Gestures)
- 4.1.1 Activity Beginner
- 4.1.2 Activity Intermediate
- 4.1.3 Activity Advanced
- 4.2.1 Service Introduction
- 4.2.2 Service Advanced
- 4.2.3 Service Mastery
- 4.3.1 BroadcastReceiver Beginner
- 4.3.2 BroadcastReceiver Advanced
- 4.4.1 ContentProvider Introduction
- 4.4.2 ContentProvider Deep Dive – Document Provider
- 4.5.1 Basic Usage of Intent
- 4.5.2 Passing Complex Data with Intent
- 5.1 Fragment Basic Overview
- 5.2.1 Fragment Example - Bottom Navigation Bar Implementation (Method 1)
- 5.2.2 Fragment Example - Bottom Navigation Bar Implementation (Method 2)
- 5.2.3 Fragment Example - Bottom Navigation Bar Implementation (Method 3)
- 5.2.4 Fragment Example - Bottom Navigation Bar + ViewPager Swipe to Switch Pages
- 5.2.5 Fragment Example - Simple Implementation of News (Shopping) App List Fragment
- 6.1 Data Storage and Access - File Storage and Reading
- 6.2 Data Storage and Access - SharedPreferences for Saving User Preferences
- 6.3.1 Data Storage and Access - Introduction to SQLite Database
- 6.3.2 Data Storage and Access - Further Exploration of SQLite Database
- 7.1.1 Android Network Programming and Learning HTTP Protocol
- 7.1.2 Learning Android HTTP Request and Response Headers
- 7.1.3 Android HTTP Request Method: HttpURLConnection
- 7.1.4 Android HTTP Request Method: HttpClient
- 7.2.1 Android XML Data Parsing
- 7.2.2 Android JSON Data Parsing
- 7.3.1 Android File Upload
- 7.3.2 Android File Download (1)
- 7.3.3 Android File Download (2)
- 7.4 Android Calling WebService
- 7.5.1 Basic Usage of WebView (Web View)
- 7.5.2 Basic Interaction Between WebView and JavaScript
- 7.5.3 Considerations for WebView in Android 4.4 and Later
- 7.5.4 WebView File Download
- 7.5.5 WebView Cache Issues
- 7.5.6 WebView Handling Error Code Information from Web Pages
- 7.6.1 Socket Learning Network Basics Preparation
- 7.6.2 Socket Communication Based on TCP Protocol (1)
- 7.6.3 Socket Communication Based on TCP Protocol (2)
- 7.6.4 Socket Communication Based on UDP Protocol
- 8.1.1 Summary of 13 Drawable Types in Android Part 1
- 8.1.2 Summary of 13 Drawable Types in Android Part 2
- 8.1.3 Summary of 13 Drawable Types in Android Part 3
- 8.2.1 Comprehensive Analysis of Bitmap (Bitmap) Part 1
- 8.2.2 OOM Issues Caused by Bitmap
- 8.3.1 Detailed Explanation of Three Drawing Tool Classes
- 8.3.2 Practical Examples of Drawing Classes
- 8.3.3 Paint API — MaskFilter (Mask)
- 8.3.4 Paint API — Xfermode and PorterDuff Detailed Explanation (Part 1)
- 8.3.5 Paint API — Xfermode and PorterDuff Detailed Explanation (Part 2)
- 8.3.6 Paint API — Xfermode and PorterDuff Detailed Explanation (Part 3)
- 8.3.7 Paint API — Xfermode and PorterDuff Detailed Explanation (Part 4)
- 8.3.8 Paint API — Xfermode and PorterDuff Detailed Explanation (Part 5)
- 8.3.9 Paint API — ColorFilter (Color Filter) (1/3)
- 8.3.10 Paint API — ColorFilter (Color Filter) (2/3)
- 8.3.11 Paint API — ColorFilter (Color Filter) (3/3)
- 8.3.12 Paint API — PathEffect (Path Effect)
- 8.3.13 Paint API — Shader (Image Rendering)
- 8.3.14 Paint Enumerations/Constants and ShadowLayer Shadow Effect
- 8.3.15 Paint API — Typeface (Font Style)
- 8.3.16 Detailed Explanation of Canvas API (Part 1)
- 8.3.17 Detailed Explanation of Canvas API (Part 2) Clipping Methods
- 8.3.18 Detailed Explanation of Canvas API (Part 3) Matrix and drawBitmapMesh
- 8.4.1 Frame Animation in Android
- 8.4.2 Tween Animation in Android
- 8.4.3 Property Animation in Android - Introduction
- 8.4.4 Property Animation in Android - Further Exploration
- 9.1 Playing Sound Effects with SoundPool (Duang~)
- 9.2 Playing Audio and Video with MediaPlayer
- 9.3 Using Camera to Take Photos
- 9.4 Using MediaRecord to Record Audio
- 10.1 TelephonyManager (Telephony Manager)
- 10.2 SmsManager (SMS Manager)
- 10.3 AudioManager (Audio Manager)
- 10.4 Vibrator (Vibrator)
- 10.5 AlarmManager (Alarm Service)
- 10.6 PowerManager (Power Service)
- 10.7 WindowManager (Window Management Service)
- 10.8 LayoutInflater (Layout Service)
- 10.9 WallpaperManager (Wallpaper Manager)
- 10.10 Sensor Topics (1) — Introduction
- 10.11 Sensor Topics (2) — Orientation Sensor
- 10.12 Sensor Topics (3) — Accelerometer/Gyroscope Sensor
- 10.12 Sensor Topics (4) — Understanding Other Sensors
- 10.14 Introduction to Android GPS
- 11.0 "2015 Latest Android Basic Beginner's Tutorial" Completion Celebration~
- 12.1 Android Practice: DrySister Viewing Girls App (First Edition) — Project Setup and Simple Implementation
- 12.2 DrySister Viewing Girls App (First Edition) — 2. Parsing Backend Data
- 12.3 DrySister Viewing Girls App (First Edition) — 3. Image Loading Optimization (Writing a Small Image Caching Framework)
- 12.4 DrySister Viewing Girls App (First Edition) — 4. Adding Data Caching (Introducing SQLite)
- 12.5 DrySister Viewing Girls App (First Edition) — 5. Code Review, Adjustment, and Logging Class Writing
- 12.6 DrySister Viewing Girls App (First Edition) — 6. Icon Creation, Obfuscation, Signing, APK Thinning, App Release