Service是什么
1.Service是一个应用组件, 它用来在后台完成一个时间跨度比较大的工作且没有关联任何界面
-
2.一个Service可以完成下面这些工作:
-
访问网络
播放音乐
文件IO操作
大数据量的数据库操作
……
3. 服务的特点:
Service在后台运行,不用与用户进行交互
即使应用退出, 服务也不会停止.
在默认情况下,Service运行在应用程序进程的主线程(UI线程)中,如果需要在Service中处理一些网络连接等耗时的操作,那么应该将这些任务放在分线程中处理,避免阻塞用户界面
区别Service与Activity?
-
Activity:
-
Activity对应一个界面
-
应用退出, Activity对象就会死亡
-
应用再次进入, 启动的Activity对象是重新创建的
-
2. Service
-
不与任何界面关联
-
应用退出, Service仍在运行
-
应用再次进入, 启动的Service还是前面运行的Service对象
Service的分类
-
1.Local Service(本地服务)
-
Service对象与Serive的启动者在同个进程中运行, 两者的通信是进程内通信
-
2.Remote Service(远程服务)
-
Service对象与Service的启动者不在同一个进程中运行, 这时存在一个进程间通信的问题, Android专门为此设计了AIDL来实现进程间通信
使用本地服务
定义service
1.定义一个类继承于Service类
public class MyService extends Service {
}
在AndroidManifest.xml中配置Service
<service android:name=".test.MyService">
<intent-filter>
<action android:name="com.atguigu.service.test.MyService" />
</intent-filter>
</service>
启动与停止Service
方式一 : 一般启动与停止
context.startService(Intent intent)
context.stopService(Intent intent)
方式二 : 绑定启动与解绑
context.bindService(Intent intent, ServiceConnection connection)
context.unbindService(ServiceConnection connection)
Service生命周期
-
1.startService(intent)
-
第一次调用 : –>构造方法()–>onCreate()–>onStartCommand()
(重要)后面再调用 : –>onStartCommand()
stopService() : –>onDestory()
2 bindService(intent, serviceConnection)
-
调用 : –>构造方法()–>onCreate()–>onBind()–>onServiceConnected()
unbindService(): (中有当前Activity与Service连接)–>onUnbind()–>onDestroy()
AIDL理解
每个应用程序都运行在自己的独立进程中,并且可以启动另一个应用进程的服务,而且经常需要在不同的进程间传递数据对象。
在Android平台,一个进程不能直接访问另一个进程的内存空间,所以要想对话,需要将对象分解成操作系统可以理解的基本单元,并且有序的通过进程边界。
AIDL (Android Interface Definition Language)
用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。
如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。
案例
服务器端
首先定义一个AIDL接口IStudentService.aidl,定义其中方法
package com.hbwj.myapplication.remote;
import com.hbwj.myapplication.remote.Student;
interface IStudentService {
Student getStudentById(int id);
}
注意: import com.hbwj.myapplication.remote.Student;一定要导入本地下的aidl下的Student
定义自定义类型Student
public class Student implements Parcelable {
private int id;
private String name;
private double price;
public Student(int id, String name, double price) {
this.id = id;
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", price=" + price +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
protected Student(Parcel in) {
this.id = in.readInt();
this.name = in.readString();
this.price = in.readDouble();
}
public static final Creator<Student> CREATOR = new Creator<Student>() {
//解包: 读取包中的数据并封装成对象
@Override
public Student createFromParcel(Parcel in) {
Log.e("TAG", "解包 createFromParcel()");
int id = in.readInt();
String name = in.readString();
double price = in.readDouble();
return new Student(id, name, price);
}
//返回一个指定大小的对象容器
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
@Override
public int describeContents() {
return 0;
}
//将当前对象的属性数据打成包: 写到包对象中
@Override
public void writeToParcel(Parcel dest, int flags) {
Log.e("TAG", "打包 writeToParcel()");
dest.writeInt(id);
dest.writeString(name);
dest.writeDouble(price);
}
}
注意: 一定要继承于Parcelable
创建文件:Student.aidl
package com.hbwj.myapplication.remote;
parcelable Student;
在Service类中使用生成的类实现业务方法
public class MyRemoteService extends Service {
public MyRemoteService() {
}
@Override
public IBinder onBind(Intent intent) {
return new StudentService();
}
//处理Student相关的业务逻辑类
class StudentService extends IStudentService.Stub {
@Override
public Student getStudentById(int id) throws RemoteException {
//处理Student相关的业务逻辑类
return new Student(id, "TOM", 10000);
}
}
}
注意:在服务器端中的manifest中需要添加注册
<service
android:name=".remote.MyRemoteService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.hbwj.myapplication.remote.MyRemoteService.Action"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</service>
-
客户端
-
复制服务端AIDL的相关定义
Android自动生成一个通信接口类
在Activity中bind远程Service,并调用业务方法
注意: 直接复制服务器端下的AIDL所有文件,包名也一起复制过去,不能修改,否则报错
随后复制Student.java
进行客户端编码
public class MainActivity extends AppCompatActivity {
private EditText et_aidl_id;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_aidl_id = (EditText) findViewById(R.id.et_aidl_id);
}
private ServiceConnection conn;
private IStudentService studentService;
public void bindRemoteService(View v) {
if (conn == null) {
Intent intent = new Intent("com.hbwj.myapplication.remote.MyRemoteService.Action");
conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
studentService = IStudentService.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
bindService(intent, conn, Context.BIND_AUTO_CREATE);
Toast.makeText(this, "绑定Service", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "已经绑定Service", Toast.LENGTH_SHORT).show();
}
}
public void invokeRemote(View v) throws RemoteException {
if (studentService != null) {
int id = Integer.parseInt(et_aidl_id.getText().toString());
Student student = studentService.getStudentById(id);
Toast.makeText(this, student.toString(), Toast.LENGTH_SHORT).show();
}
}
public void unbindRemoteService(View v) {
if (conn != null) {
unbindService(conn);
conn = null;
studentService = null;
Toast.makeText(this, "解绑Service", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "还未绑定Service", Toast.LENGTH_SHORT).show();
}
}
}