Service,顾名思义就是服务的意思,就是要隐藏在UI后面悄悄搞事情的东西,而且还耗时,不过脸皮厚,一般不会被系统杀死.接下来我总结一下它的用法:
一.start启动
public class MainActivity extends AppCompatActivity {
private boolean mbound;
private IAidl cat;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startClick(View v){
Intent intent = new Intent(this, MyService.class);
startActivity(intent);
}
public void stopClick(View v){
Intent intent = new Intent(this, MyService.class);
stopService(intent);
}
}
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
//主要运行的地方
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//在这里你可以通过intent传过来的数据,对它为所欲为了
return super.onStartCommand(intent, flags, startId);//有四种返回值
}
}
//可别忘了这个
<service
android:name=".MyService"
android:enabled="true"
android:exported="true" />
二.boundService(三种使用方式):
Bound Service的主要特性在于Service的生命周期是依附于Client的生命周期的,当Client不存在时,Bound Service将执行onDestroy,同时通过Service中的Binder对象可以较为方便进行Client-Service通信。
1.第一种的使用不能进行通信,但是简单啊.(这个代码我是复制别人的,不过流程是对的)
public class MyBindService extends Service {
//在Service里为所欲为
public static final String TAG = "MyBindService";
private MyBinder mBinder = new MyBinder();
public class MyBinder extends Binder {
MyBindService getService() {
return MyBindService.this;
}
}
@Override
public void onCreate() {
super.onCreate();
Log.w(TAG, "in onCreate");
}
@Override
public IBinder onBind(Intent intent) {
Log.w(TAG, "in onBind");
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.w(TAG, "in onUnbind");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.w(TAG, "in onDestroy");
}
}
public class BActivity extends Activity {
public static final String TAG = "BActivity";
private Button bindServiceBtn;
private Button unbindServiceBtn;
private Button startIntentService;
private Intent serviceIntent;
private ServiceConnection sc = new MyServiceConnection();
private MyBinder mBinder;
private MyBindService mBindService;
private boolean mBound;//注意这里很重要,对服务的断开状态进行记录
//继承ServiceConnection接口,实现服务的连接与断开,不过这里只是的到服务的实例,真正的连接与断开还是要start和stop的
private class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
Log.w(TAG, "in MyServiceConnection onServiceConnected");
mBinder = (MyBinder) binder;
mBindService = mBinder.getService();//得到实例
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
Log.w(TAG, "in MyServiceConnection onServiceDisconnected");
mBound = false;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.b);
bindServiceBtn = (Button) findViewById(R.id.bind_service);
unbindServiceBtn = (Button) findViewById(R.id.unbind_service);
startIntentService = (Button) findViewById(R.id.start_intentservice);
bindServiceBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(BActivity.this, MyBindService.class);
bindService(intent, sc, Context.BIND_AUTO_CREATE);
}
});
unbindServiceBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
excuteUnbindService();
}
});
startIntentService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(BActivity.this, MyIntentService.class);
startService(intent);
}
});
}
private void excuteUnbindService() {
if (mBound) {
unbindService(sc);
mBound = false;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.w(TAG, "in onDestroy");
excuteUnbindService();
}
}
2.使用messager
public class MyMessagerService extends Service {
public static final int SAY_HELLO = 0x1;
public MyMessagerService() {
}
@Override
public IBinder onBind(Intent intent) {
return messenger.getBinder();
}
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case SAY_HELLO:
String info = (String) msg.obj;
//在这里你可以把处理后的它传给client
Toast.makeText(getApplicationContext(), info, Toast.LENGTH_SHORT).show();
break;
}
}
};
private Messenger messenger = new Messenger(handler);//对获取到的信息进行处理
}
activity里这样写
Messenger mService;
boolean flag = false;
private ServiceConnection conn2 = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = new Messenger(service);
flag = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
flag = false;
mService = null;
}
};
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, MyMessagerService.class);
bindService(intent, conn2, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if(flag){
unbindService(conn2);
}
}
public void messagerClick(View v){
Message msg = Message.obtain();
msg.what = MyMessagerService.SAY_HELLO;
msg.obj = "my body";
try {
mService.send(msg);//将消息发到Service那边
} catch (RemoteException e) {
e.printStackTrace();
}
}
3.使用.aidl进行client与Service之间更为灵活的通信
我这里使用aidl文件进行数据的传输.所以你要先创建一个aidl文件.我这里直接放代码了.
aidl文件
// IAidl.aidl
package com.example.administrator.serivce;
import com.example.administrator.serivce.Person;
// Declare any non-default types here with import statements
interface IAidl {
//这里的通信可不只是数据的通信,也可以使用其中的方法.
void setName(String name);
String desc();
Person getPerson();
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
//定义返回的参数类型
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
}
这里因为要传对象,所以要将对象序列化.
public class Person implements Parcelable {
public String name;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
public static final Parcelable.Creator<Person> CREATOR
= new Creator<Person>() {
@Override
public Person createFromParcel(Parcel source) {
Person p = new Person();
p.name = source.readString();
return p;
}
@Override
public Person[] newArray(int size) {
return new Person[0];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
}
}
这里因为涉及到对象的传输,你还有创建一个IPerson.aidl文件,就像下面这样写.
// IPerson.aidl
package com.example.administrator.serivce;
parcelable Person;
aidl的实现类
public class CatImpl extends IAidl.Stub{
//这个类是aidl文件接口的具体实现类,当你调用其中的方法时,就会实现其中的具体过程.
private String Name;
@Override
public void setName(String name) throws RemoteException {
name = Name;
}
@Override
public String desc() throws RemoteException {
return "my name is bobo";
}
@Override
public Person getPerson() throws RemoteException {
Person p = new Person();
p.name = "jiangbo";
return p;
}
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
}
activity里这样写
private IAidl cat;//这个是一个接口,当你创建好aidl文件后,系统会自动为你创建这个接口,你只需继承它,实现它的方法就行,就是上面的那个catImpl类
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
cat = IAidl.Stub.asInterface(service);//实际是得到Service类里onBind方法里的具体实例,就是获取到catImpl
mbound = true;
Toast.makeText(MainActivity.this, "bound", Toast.LENGTH_SHORT).show();
}
@Override
public void onServiceDisconnected(ComponentName name) {
mbound = false;
}
};
public void boundClick(View v){
Intent intent = new Intent(this, MyBoundService.class);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
public void callClick(View v){
if(cat == null) return;
try {
cat.setName("");//获取到catImpl后,就把你想要处理的东西,放在这个实现类的方法里处理就行了.
//当然你把值传过去,它也会返回值给你的,这个就看你定义的方法了.
Toast.makeText(MainActivity.this, cat.desc(), Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void unboundClick(View v){
if(mbound){
unbindService(conn);
Toast.makeText(this, "unbound", Toast.LENGTH_SHORT).show();
mbound = false;
}
}
Service.
public class MyBoundService extends Service {
public MyBoundService() {
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onRebind(Intent intent) {
super.onRebind(intent);
}
@Override
public IBinder onBind(Intent intent) {
return (IBinder) new CatImpl();
}
@Override
public boolean onUnbind(Intent intent) {
return true;
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
6.IntentService
IntentService是系统提供给我们的一个已经继承自Service类的特殊类,IntentService特殊性是相对于Service本身的特性而言的:
1.默认直接实现了onBind(..)方法,直接返回null,并定义了抽象方法onHandlerIntent(..),用户自定义子类时,需要实现此方法;
2.onHandlerIntent(..)主要就是用来处于相应的”长期“任务的,并且已经自动在新的线程中,用户无语自定义新线程;
3.当”长期“任务执行完毕后(也就是onHandlerIntent(..)执行完毕后),此IntentService将自动结束,无需人为调用方法使其结束;
4.IntentService处于任务时,是按照队列的方式一个个去处理,而非真正意义上的多线程并发方式。
public class MyIntentService extends IntentService {
public MyIntentService(String name) {
super(name);
}
@Override
protected void onHandleIntent(Intent intent) {
new Thread(new Runnable() {//避免与主线程冲突,会阻塞;
@Override
public void run() {
for(int i = 0; i < 5; i++){
Toast.makeText(MyIntentService.this, "Come on!", Toast.LENGTH_SHORT).show();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(i == 3){
MyIntentService.this.stopSelf();
}
}
}
});
}
}
public void IntentClick(View v){
Intent intent = new Intent(this, MyIntentService.class);
startActivity(intent);
}
7.startforground
前台服务是那些被认为用户知道(用户认可所认可)且在系统内存不足的时候不允许系统杀死的服务。前台服务必须给状态栏提供一个通知,它被放到正在运行(Ongoing)标题之下——这就意味着通知只有在这个服务被终止或从前台主动移除通知后才能被解除。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand()");
// 在API11之后构建Notification的方式
Notification.Builder builder = new Notification.Builder
(this.getApplicationContext()); //获取一个Notification构造器
Intent nfIntent = new Intent(this, MainActivity.class);
builder.setContentIntent(PendingIntent.
getActivity(this, 0, nfIntent, 0)) // 设置PendingIntent
.setLargeIcon(BitmapFactory.decodeResource(this.getResources(),
R.mipmap.ic_large)) // 设置下拉列表中的图标(大图标)
.setContentTitle("下拉列表中的Title") // 设置下拉列表里的标题
.setSmallIcon(R.mipmap.ic_launcher) // 设置状态栏内的小图标
.setContentText("要显示的内容") // 设置上下文内容
.setWhen(System.currentTimeMillis()); // 设置该通知发生的时间
Notification notification = builder.build(); // 获取构建好的Notification
notification.defaults = Notification.DEFAULT_SOUND; //设置为默认的声音
// 参数一:唯一的通知标识;参数二:通知消息。
startForeground(110, notification);// 开始前台服务
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy()");
stopForeground(true);// 停止前台服务--参数:表示是否移除之前的通知
super.onDestroy();
}
如果这样写,未免有点太简单了,只不过是Service+Notification而已,所以了,如果加入广播来通知Notification做出相应的变化就好了.
提示一下:自定义Notification+为自定义的布局添加点击事件+事件当然就是广播啦