1.1Service——服务
什么是服务?
它也是一个程序。只不过是没有界面的程序。
在windows也是存在服务的。
Android中使用Service实现没有界面的程序,使用场景是:
例如:微信已经关闭,但是依然可以收到外界的消息,这个程序就是一个服务。
当手机用户去往另一个城市,手机自动显示新的城市和实时的天气,背后也是一个服务。
音乐播放时,即使息屏也是可以听到声音,音乐界面已经关闭,但是音乐仍在播放,这是一个服务。
缓存电影到无网的环境播放,下载并不影响正在播放的电影,下载程序就是一个服务程序。
Service是Android4大组件之一,哪些属于android的4大组件:
(1)Activity(活动,也就是程序的界面,开发的实践1个Activity+多个fragment)
(2)Service(服务,没有界面的程序)
(3)BroadCastReceiver(广播接收者,BroadCastSender,跨程序的通信)
(4)ContentProvider(内容提供者,跨程序的数据源调用,ContentResolver,ContentObserver)
使用Service需要注意的事项:
(1)通常线程是在Activity中发起,那么这个线程的生命周期就属于这个Activity,当这个Activity被回收后,线程就会中断。
例如:A(Actvity)B(Activity)C(Activity),再返回A,BC如果被回收,C中发起的线程就会中断。
C如果发起一个下载的程序,在C被回收时,这个下载程序也会被中断。
activity_a.xml
温馨提示:宝,你要学会自己打代码哦!这里就不放源码了,快来实操一遍啊!
activity_b.xml
activity_c.xml
AActivity.java
CActivity.java
效果:
CActivity被回收后(日志停止输出):
1.2创建第一个服务
如何创建Activity?
(1)创建一个类继承Activity
(2)注册Activity
(3)启动Activity
startActivity(intent)
如何创建服务?
(1)创建一个类继承Service
(2)注册
(3)启动Service
startService(intent)
【案例】
MyService.java
MainActivity.java
androidManifest.xml
日志:
2.1Service的生命周期(通过不同生命周期阶段的回调方法来观察)
如何建立一个Service?
(1)自定义一个类,继承Service
(2)注册
(3)启动,startService(intent)
Service的生命周期分为两种不同的Service来观察:
(1)Unbound模式下的生命周期(非绑定式)
回调方法有些哪些?
onCreate、onStartCommand、onDestroy
【案例】
activity_main.xml
MyService.java
MainActivity.java
androidManifest.xml
效果:
日志:
(2)Bounded模式下的生命周期(绑定式)
原理图。
步骤:
1)引入Binder子类,在其中实现调用服务的方法。获得一个Binder实例,这个binder实例可以对Service的生命周期进行控制,这个实例是通过onBind方法返回出去的。
2)编写有关Service的生命周期方法(onCreate\onDestroy)
3)编写有关Service的相关服务方法(不是生命周期方法)
4)引入ServiceConnection,目的是将Binder实例传递给Activity
5)在Activity中使用Binder对Service进行控制。
Bounded方式用到的启动服务的方法:
bindService(参数1:intent,参数2:ServiceConnection,参数3:BIND_AUTO_CREATE)
参数1:表示启动什么服务
参数2:binder实例从哪个连接对象中获取
参数3:启动方式,推荐使用:自动创建。
【案例】
activity_main2.xml
MyService2.java
MainActivity2.java
AndroidManifest.xml
效果:
日志:
2.2Service生命周期2(音乐播放器)
日志:
Service两种启动模式的生命周期
Service的启动方式有2种:
unbounded:无绑定的形式。StartService(intent),特征:服务一旦启动后,不能控制,只能停止,因此不能干预运行的中间过程。例如:听音乐,没有界面,音乐在播放,只能播放(Start)和停止(stop)。停止后,只能从头开始。
方法:startService(intent)、stopService(intent)
Bounded:绑定的形式。bindService(intent,conn,BIND_AUTO_CREATE),特征:服务启动后,能对服务全过程进行控制。例如:听音乐的过程,没有界面,音乐可以播放可以暂停。
方法:bindService(intent,conn,BIND_AUTO_CREATE)(启动服务)、unbindService(conn)(停止服务)
2.使用IntentService
默认情况下Service是运行在主线程中,主线程是不能够运行耗时任务的,如果运行耗时任务就会出现“ANR”(application not responding,应用程序无响应,卡顿)。Android对于超过一定时间限制的任务,就会出现ANR提示。
【案例】在service中运行耗时任务,体验ANR。
activity_main2.xml
MyService2.java
MainActivity2.java
效果:反复点击按钮出现ANR
日志:
activity_main
<?xml version="1.0" encoding="utf-8"?>
<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/btnBind"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="绑定"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnPlay"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="播放"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnBind" />
<Button
android:id="@+id/btnPause"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="暂停"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnPlay" />
<Button
android:id="@+id/btnUnbind"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="卸绑"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnPause" />
</androidx.constraintlayout.widget.ConstraintLayout>
activity_main2
<?xml version="1.0" encoding="utf-8"?>
<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">
<Button
android:id="@+id/btnStart"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="启动耗时任务"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
services包下
MyService
package com.example.myapplication.services;
import android.app.Service;
import android.content.Intent;
import android.nfc.Tag;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
private static final String TAG = "MyService";
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG,"onBind");
return new MyBinder();
}
private void playInService(){
Log.i(TAG,"音乐正在播放...");
}
private void pauseInService(){
Log.i(TAG,"音乐暂停播放...");
}
public class MyBinder extends Binder{
public void Paly(){
playInService();
}
public void pause(){
pauseInService();
}
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG,"onCreate");
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG,"onUnbind");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
Log.i(TAG,"onDestory");
super.onDestroy();
}
}
MyService2
package com.example.myapplication.services;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class MyService2 extends Service {
private static final String TAG = "MyService";
public MyService2() {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
}
private Long index=0l;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Long endTime=System.currentTimeMillis()+100*1000;
Log.i(TAG,"耗时任务开始执行...");
while (System.currentTimeMillis()<endTime){
try {
Thread.sleep(100);
Log.i(TAG,"执行次数:"+index);
} catch (InterruptedException e){
e.printStackTrace();
}
}
Log.i(TAG,"耗时任务结束执行...");
return super.onStartCommand(intent,flags,startId);
}
}
MainActivity
package com.example.myapplication;
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.util.Log;
import android.view.View;
import android.widget.Button;
import com.example.myapplication.services.MyService;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MyService";
private Button btnBind,btnPlay,btnPause,btnUnbind;
private MyService.MyBinder myBinder;
ServiceConnection coon=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.i(TAG,"onServiceConnected");
myBinder= (MyService.MyBinder) iBinder;
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnBind = findViewById(R.id.btnBind);
btnPlay = findViewById(R.id.btnPlay);
btnPause = findViewById(R.id.btnPause);
btnUnbind = findViewById(R.id.btnUnbind);
btnBind.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent=new Intent(MainActivity.this,MyService.class);
Log.i(TAG,"bindService");
bindService(intent,coon,BIND_AUTO_CREATE);
}
});
btnPlay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (myBinder!=null)
myBinder.Paly();
}
});
btnPause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (myBinder!=null);
myBinder.pause();
}
});
btnUnbind.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (myBinder!=null)
myBinder.pause();
}
});
btnUnbind.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.i(TAG,"unbindService");
unbindService(coon);
myBinder=null;
}
});
}
}
MainActivity2
package com.example.myapplication;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.example.myapplication.services.MyService2;
public class MainActivity2 extends AppCompatActivity {
private Button btnStart;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
btnStart = findViewById(R.id.btnStart);
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent=new Intent(MainActivity2.this, MyService2.class);
startService(intent);
}
});
}
}
后续我会继续写的
么么叽么么叽么么哒!