Service
不是一个独立的进程,也不是线程
种类:Local,Remote
类型:前台,后台
启动方式:start ,Bind
在AndroidManifest.xml中声明:
<service android:name=".MusicService" />
service with start :
package com.jsc4.aboutactivity;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
public class MusicService extends Service {
private static final String TAG = MusicService.class.getSimpleName();
private MediaPlayer mMediaPlayer;
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate");
mMediaPlayer = MediaPlayer.create(this, R.raw.lovelove);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand");
mMediaPlayer.start();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy");
mMediaPlayer.stop();
super.onDestroy();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind");
return null;
}
}
Service声明周期
service with bind:
MusicButtonActivity.java
package com.jsc4.aboutactivity;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.widget.Button;
public class MusicButtonActivity extends AppCompatActivity implements View.OnClickListener {
private Button mStartButton;
private Button mStopButton;
private MusicService mMusicService;
private ServiceConnection mServiceConnection = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicService.LocalBinder localBinder = (MusicService.LocalBinder) service;
mMusicService = localBinder.getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_music_button);
mStartButton = findViewById(R.id.start_music_button);
mStopButton = findViewById(R.id.stop_music_button);
mStartButton.setOnClickListener(this);
mStopButton.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.start_music_button:
startService(new Intent(MusicButtonActivity.this, MusicService.class));
bindService(new Intent(MusicButtonActivity.this, MusicService.class), mServiceConnection, BIND_AUTO_CREATE);
break;
case R.id.stop_music_button:
unbindService(mServiceConnection);
stopService(new Intent(MusicButtonActivity.this, MusicService.class));
break;
case R.id.get_music_progress_button:
if(mMusicService != null){
int progress = mMusicService.getMusicPlayProgress();
}
break;
}
}
}
MusicService.java
package com.jsc4.aboutactivity;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
public class MusicService extends Service {
private static final String TAG = MusicService.class.getSimpleName();
private MediaPlayer mMediaPlayer;
private IBinder mIBinder = new LocalBinder();
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate");
mMediaPlayer = MediaPlayer.create(this, R.raw.lovelove);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand");
mMediaPlayer.start();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy");
mMediaPlayer.stop();
super.onDestroy();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind");
return mIBinder;
}
public class LocalBinder extends Binder {
MusicService getService(){
return MusicService.this;
}
}
public int getMusicPlayProgress(){
return 18;
}
}
工作流程:
Activity中的这句话(bindService(new Intent(MusicButtonActivity.this, MusicService.class), mServiceConnection, BIND_AUTO_CREATE);
)会把connection传给service,service中的这句话(return mIBinder;
)会把mIBinder传回去,传给刚才传进来的connection里,在Activity中就可以收到了:
private ServiceConnection mServiceConnection = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicService.LocalBinder localBinder = (MusicService.LocalBinder) service;
mMusicService = localBinder.getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
Activity收到的IBinder对象含有关键信息,因为在service中这个IBinder对象中定义了getService方法,这样就可以在Activity中拿到Service
了。
在service中定义了一些公共方法
,如public int getMusicPlayProgress();
,这样,在Activity中,通过service对象,就可以获取到这些公共方法了。
IntentService
activity中:
Intent intent = new Intent(MusicButtonActivity.this, MusicService.class);
intent.putExtra("msg", "携带的信息");
startService(intent);
IntentService中:
@Override
protected void onHandleIntent(@Nullable Intent intent) {
// intent队列 排队,像MessageQueue 同步操作:排队领书,处理Intent数据
// stopSelf(); // 停止本身,此处不必使用
if(intent != null){
}
}
整个IntentService:
package com.jsc4.aboutactivity;
import android.app.IntentService;
import android.content.Intent;
import androidx.annotation.Nullable;
public class TestIntentService extends IntentService {
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public TestIntentService(String name) {
super(name);
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
// do more work is wrong UI线程 > 10s时,ANR(应用程序无响应)
// 把耗时操作放到子线程中
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
}
});
thread.start();
return super.onStartCommand(intent, flags, startId);
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
// intent队列 排队,像MessageQueue 同步操作:排队领书,处理Intent数据
// stopSelf(); // 停止本身,此处不必使用
if(intent != null){
}
}
}
注意
Service中不适合做耗时操作,它属于UI线程,所以要创建一个子线程去做耗时操作。
模板
MainActivity:
public class MainActivity extends AppCompatActivity {
private MyService mMyService;
private ServiceConnection mServiceConnection = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
MyService.LocalBinder localBinder = (MyService.LocalBinder) service;
mMyService = localBinder.getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startService(View view){
startService(new Intent(MainActivity.this, MyService.class));
bindService(new Intent(MainActivity.this, MyService.class), mServiceConnection, BIND_AUTO_CREATE);
}
public void stopService(View view){
unbindService(mServiceConnection);
stopService(new Intent(MainActivity.this, MyService.class));
}
public void updataProgress(View view){
if(mMyService != null){
int progress = mMyService.getProgress();
}
}
}
xml:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/startService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="start"
android:onClick="startService"
app:layout_constraintBottom_toTopOf="@+id/guideline2"
app:layout_constraintEnd_toStartOf="@+id/guideline"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toTopOf="@+id/guideline2" />
<Button
android:id="@+id/stopService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Stop"
android:onClick="stopService"
app:layout_constraintBottom_toTopOf="@+id/guideline3"
app:layout_constraintEnd_toStartOf="@+id/guideline"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toTopOf="@+id/guideline3" />
<Button
android:id="@+id/updataProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Update"
android:onClick="updataProgress"
app:layout_constraintBottom_toTopOf="@+id/guideline4"
app:layout_constraintEnd_toStartOf="@+id/guideline"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toTopOf="@+id/guideline4" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.2" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.4" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.6" />
</androidx.constraintlayout.widget.ConstraintLayout>
Service:
public class MyService extends Service {
private static final String TAG = MyService.class.getSimpleName();
private IBinder mIBinder = new MyService.LocalBinder();
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand");
// 开始工作
// ...
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.i(TAG, "onDestroy");
// 停止工作
// ...
super.onDestroy();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind");
return mIBinder;
}
public class LocalBinder extends Binder {
MyService getService(){
return MyService.this;
}
}
public int getProgress(){
return 18; // 可以自行定义逻辑
}
}