您的位置:首页 > 移动开发 > Android开发

本地service【Android】

2016-08-06 21:04 441 查看
本地service是一个应用组件,它用来在后台完成一个时间跨度较大的工作且没有关联任何界面

一 服务的特点:

Service在后台运行,不用与用户进行交互
即使用户退出,服务也不会停止
在默认情况下,Service运行在应用程序进程的主线程中,如果需要在Service中处理一些网络连接等耗时的操作,那么应该将这些任务放在分线程中处理,避免阻塞用户界面

二 Service和Activity的区别:

Activity:

Activity对应一个界面
应用退出时,Activity对象就会死亡
应用再次进入,启动的Activity对象是重新创建的

Service

不用任何界面关联
应用退出,Service仍在运行
应用再次进入,启动的Service还是前面运行的Service对象

三 Service和Thread的区别

Service

用来在后台完成一个时间跨度比较大的工作的应用组件
Service的生命周期方法运行在主线程,如果Service想做持续时间比较长的工作,需要启动一个分线程(Thread)
应用退出:Service不会停止
应用再次进入:可以与正在运行的Service进行通信

Thread

用来开启一个分线程的类,做一个长时间的工作
Thread对象的run()在分线程执行
应用退出:Thread不会停止
应用再次进入:不能再控制前面启动的Thread对象

四 Service的分类

Local Service(本地服务)

Service对象与Service的启动者在同个进程中运行,两者的通信时进程内的通信

Remote Service(远程服务)

Service对象与Service的启动者不在同一个进程中进行,这时存在一个进程间通信的问题,Android专门为此设计了AIDL来实现进程间通信

五 Service的使用

1.需要定义一个类继承于Service类

2.在AndroidMainfest.xml中配置Service

<span style="font-size:14px;"><Service android:name=".test.MyService">
<intent-filter>
<action android:name="随便一个字符串"/>
</intent-filter>
</service></span>


六 启动与停止Service

1.方式一:  一般启动与停止

context.startService(Intentintent)

context.stopService(Intentintent)

2.方式二 : 绑定启动与解绑

context.bindService(Intentintent, ServiceConnectionconnection)

context.unbindService(ServiceConnectionconnection)

七  Service的生命周期:



 注意:每次startService都会调用Service的onStartCommand()

八  什么时候会用到反射?

     1). 功能清单清单文件: 配置应用组件的全类名
     2). 布局文件 : 视图标签
     3). 显式意图: 指定类的Class对象
     4). 调用系统隐藏的API : 使用Class.forName("全类名")调用
     哪些情况使用了反射?
          1. 指定类名/全类名字符串
          2. 使用反射相关API:  Class | Method | Field

九  AIDL理解

每个应用程序都运行在自己的独立进程中,并且可以启动另一个应用进程的服务,而且经常需要在不同的进程间传递数据对象。

在Android平台,一个进程不能直接访问另一个进程的内存空间,所以要想对话,需要将对象分解成操作系统可以理解的基本单元,并且有序的通过进程边界。

AIDL(Android Interface Definition Language)

用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。

如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。

八 定义一个AIDL接口,如果需要使用自定义类型的数据对象比如(student)把student进行封装时需要实现Parelable接口,并且需要创建一个跟此对象一样名字的AIDL文件student.aidl

package com.atguigu.service.test.remote;
parcelable Student;
十  案列-----开启两个进程,一个进程和另一个建立连接后,这个进程在输入框中输入id后,会显示出该学生的相关信息

主要通过service和activity通信

第一步:需要在被连接的进程(新建的项目Remote)中封装一个类student需要实现Parelable接口

package shangguigu.java.remote;

import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

/**
* Created by Dell on 2016/8/6.
*/
public class Student implements Parcelable{
int id;
String name;
int age;

public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}

@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}

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 int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public Student() {

}

@Override
public int describeContents() {
return 0;
}

//打包
@Override
public void writeToParcel(Parcel dest, int flags) {
Log.i("tag","打包");
dest.writeInt(id);
dest.writeString(name);
dest.writeInt(age);
}

public static final Parcelable.Creator<Student> CREATOR = new Creator<Student>() {
@Override
public Student createFromParcel(Parcel source) {
Log.i("tag","解包");
//解包
int id = source.readInt();
String name = source.readString();
int age = source.readInt();
return new Student(id,name,age);
}

//返回指定大小的容器
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
}
第二步需要创建一个student.adil,然后运行一下点击这个键



package shangguigu.java.remote;
parcelable Student;


第三步  需要创建一个aidl如MyService.aidl里面需要使用Student虽然两个在一个包下,但是还得继续导入包删去没用的代码

// MyService.aidl
package shangguigu.java.remote;
import shangguigu.java.remote.Student;
// Declare any non-default types here with import statements

interface MyService {
Student getStudentById(int id);
}


第四步:需要创建一个Service

package shangguigu.java.remote;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class RemoteService extends Service {
public RemoteService() {
}

@Override
public IBinder onBind(Intent intent) {
Log.i("tag","onBind()");
return new StudentService();
}

@Override
public boolean onUnbind(Intent intent) {
Log.i("tag","onUnbind()");
return super.onUnbind(intent);
}

class StudentService extends MyService.Stub {

@Override
public Student getStudentById(int id) throws RemoteException {
Log.i("tag","service getStudentById()");
return new Student(1,"hahah",10);
}
}
}


以及需要在mainfest中进行注册

<service android:name=".RemoteService">
<intent-filter>
<action android:name="fanny"/>//这里的name可以随意写,但是需要记住,以后会需要
</intent-filter>
</service>
第五步:新建一个新的项目,ServiceClient

需要将第一个项目里的aidl相关的文件复制到这个项目里,注意:包名也必须一样有student    student.aidl   MyService.aidl

需要在布局文件中写布局文件,主要有一个文本编辑框TextView   3个Button一个用于连接Service一个用于断开连接,最后一个用于显示

在mainActivity的主文件中编写代码

package shangguigu.java.serviceclient;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import shangguigu.java.remote.MyService;
import shangguigu.java.remote.Student;

public class MainActivity extends AppCompatActivity {

private EditText et_main;
private  MyService myService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_main = (EditText) findViewById(R.id.et_main);
}

public void ConnectService (View v) {
Intent intent = new Intent("fanny");//需要连接的Service再mainfest注册时填写的的

if (conn == null) {
conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("tag","onServiceConnected");
myService = MyService.Stub.asInterface(service);

}
@Override
public void onServiceDisconnected(ComponentName name) {

}
};
bindService(intent,conn,BIND_AUTO_CREATE);
Toast.makeText(this,"绑定service",Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this,"已经绑定service",Toast.LENGTH_SHORT).show();
}
}
private ServiceConnection conn;
public void SelectStudent (View v) throws RemoteException {
if (conn !=null) {
if (myService!=null) {
int id = Integer.parseInt(et_main.getText().toString());
Log.i("tag",id+"");
Student student = myService.getStudentById(id);
int _id = student.getId();
if ((id+"").equals(_id+"")) {
Toast.makeText(this,student.toString(),Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(this,"没有这条信息",Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(this,"没有这条信息",Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(this,"没有绑定service",Toast.LENGTH_SHORT).show();
}

}
public void disConnectService (View v) {
if (conn != null) {
unbindService(conn);
conn = null;
Toast.makeText(this,"解除绑定",Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this,"没有绑定",Toast.LENGTH_SHORT).show();
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android service