service,android四大组件之一,是一个长期运行在应用后台的android组件,它没有与用户交互的界面。
-------------------------------------------------------------
目录:
service分类简介
一. 如何创建一个service?
二.如何启动/关闭service?
三.如何绑定/解绑service?
四.如何创建前台service?
五.service的生命周期?
六.如何让service与activity进行交互?
七.使用AIDL绑定远程服务
八.service与thread的区别?
------------------------------------------------------------
service分类简介:
一. 如何创建一个service?
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class ServiceExample extends Service
{
@Override
public IBinder onBind(Intent intent)
{
return null;
}
}
<service android:name="com.example.xxx"></service>
android:name:服务类名
android:label:服务的标签,如果此项不设置,那么默认显示的服务名则为类名
android:icon:服务的图标
android:permission:申明此服务的权限,这意味着只有提供了该权限的应用才能控制或连接此服务
android:process:表示该服务是否运行在另外一个进程,如果设置了此项,那么将会在包名后面加上这段字符串表示另一进程的名字(即远程服务)
android:enabled:如果此项设置为 true,那么 Service 将会默认被系统启动,不设置默认此项为 false
android:exported:表示该服务是否能够被其他应用程序所控制或连接,不设置默认此项为 false
具体的使用案例我放在了后面,请继续向下看。
二.如何启动/关闭service?
startService(Intent intent)//启动服务
stopService(Intent intent)//关闭服务
ntent用于指定我们要开启的服务,可以用显示意图也可以用隐式意图。显式意图很简单,直接指明开启的服务的类名即可,像这样:
Intent intent1 = new Intent(this,MyService.class);
如果使用隐式意图,首先我们需要在配置service时增加一个意图过滤器:
<service android:name="com.example.service.PayService">
<intent-filter>
<action android:name="com.example.pay"/>
</intent-filter>
</service>
然后我们开启服务的时候,也指定action:
Intent intent = new Intent("com.example.pay");
三.如何绑定/解绑service?
public boolean bindService(Intent service, ServiceConnection conn, int flags)//绑定
public void unbindService(ServiceConnection conn)//解绑
public interface ServiceConnection {
public void onServiceConnected(ComponentName name, IBinder service);
public void onServiceDisconnected(ComponentName name);
}
try
{
if(conn != null)
unbindService(conn);
} catch (Exception e)
{
}
四.如何创建前台service?
public final void startForeground(int id, Notification notification)
public final void stopForeground(boolean removeNotification)
首先新建一个android工程,然后创建一个类继承service:
package com.example.foregroundservicedemo.service;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import com.example.foregroundservicedemo.MainActivity;
import com.example.foregroundservicedemo.R;
public class MyService extends Service
{
@Override
public IBinder onBind(Intent intent)
{
return null;
}
@Override
public void onCreate()
{
Notification notification = new Notification(R.drawable.notification, "您有一条新通知", System.currentTimeMillis());
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,notificationIntent, 0);
notification.setLatestEventInfo(this, "通知的标题", "通知的内容",pendingIntent);
startForeground(1, notification); //开启前台服务
}
@Override
public void onDestroy()
{
stopForeground(true);//停止前台服务,并销毁通知
}
}
<service android:name="com.example.foregroundservicedemo.service.MyService"></service>
最后,我们编写一个activity,添加两个按钮分别用于启动/停止服务,代码很简单,下面只贴出onclick方法:
public void onClick(View v)
{
switch (v.getId())
{
case R.id.but_start:
Intent intent = new Intent(this,MyService.class);
this.startService(intent);
break;
case R.id.but_stop:
Intent intent2 = new Intent(this,MyService.class);
this.stopService(intent2);
break;
}
}
五.service的生命周期?
(1). 被启动的服务的生命周期:如果一个Service被某个Activity 调用 Context.startService 方法启动,那么不管是否有Activity使用bindService绑定或unbindService解除绑定到该Service,该Service都在后台运行。如果一个Service被startService 方法多次启动,那么onCreate方法只会调用一次,onStart将会被调用多次(对应调用startService的次数),并且系统只会创建Service的一个实例(因此你应该知道只需要一次stopService调用)。该Service将会一直在后台运行,而不管对应程序的Activity是否在运行,直到被调用stopService,或自身的stopSelf方法。当然如果系统资源不足,android系统也可能结束服务。
(2). 被绑定的服务的生命周期:如果一个Service被某个Activity 调用 Context.bindService 方法绑定启动,不管调用 bindService 调用几次,onCreate方法都只会调用一次,同时onStart方法始终不会被调用。当连接建立之后,Service将会一直运行,除非调用Context.unbindService 断开连接或者之前调用bindService 的 Context 不存在了(如Activity被finish的时候),系统将会自动停止Service,对应onDestroy将被调用。
至于第三种比较特殊了,我们也来总结下它的生命周期:package com.example.servicedemo2.myservice;
import com.example.servicedemo2.binder.IService;
import android.app.Service;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class MyService extends Service
{
private static final String TAG = "MyService";
@Override
public void onCreate()
{
Log.i(TAG,"服务被创建");
}
@Override
public IBinder onBind(Intent intent)
{
Log.i(TAG,"服务被绑定");
return new MyBinder();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.i(TAG,"onstartCommand方法调用,startId = "+startId);
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy()
{
Log.i(TAG,"服务被销毁");
}
private class MyBinder extends Binder implements IService
{
@Override
public void func()
{
myServiceFunc();//通过一个binder将服务中的方法暴露给外界
}
}
/**
* 服务中的私有的方法
*/
private void myServiceFunc()
{
Toast.makeText(getApplicationContext(),"成功调用了服务中的方法...", 0).show();
}
@Override
public boolean onUnbind(Intent intent)
{
Log.i(TAG,"服务被解除绑定...");
return super.onUnbind(intent);
}
}
package com.example.servicedemo2;
import com.example.servicedemo2.binder.IService;
import com.example.servicedemo2.myservice.MyService;
import android.app.Activity;
import android.app.Service;
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.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
/**
* @author Rowand jj
*
*/
public class MainActivity extends Activity implements OnClickListener
{
protected static final String TAG = "MainActivity";
private Button but_start,but_stop,but_bind,but_unbind,but_func;
private IService s = null;
private ServiceConnection conn = null;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
but_start = (Button) findViewById(R.id.but_start);
but_stop = (Button) findViewById(R.id.but_stop);
but_bind = (Button) findViewById(R.id.but_bind);
but_unbind = (Button) findViewById(R.id.but_unbind);
but_func = (Button) findViewById(R.id.but_func);
but_start.setOnClickListener(this);
but_stop.setOnClickListener(this);
but_bind.setOnClickListener(this);
but_unbind.setOnClickListener(this);
but_func.setOnClickListener(this);
}
@Override
public void onClick(View v)
{
switch (v.getId())
{
case R.id.but_start:
Intent intent1 = new Intent(this,MyService.class);
this.startService(intent1);
break;
case R.id.but_stop:
Intent intent2 = new Intent(this,MyService.class);
this.stopService(intent2);
break;
case R.id.but_bind:
Intent intent3 = new Intent(this,MyService.class);
conn = new ServiceConnection()
{
@Override
public void onServiceDisconnected(ComponentName name)
{
Log.i(TAG,"onServiceDisconnected运行了...");
}
@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
Log.i(TAG,"成功连接上了服务,现在可以调用服务中的方法了");
s = (IService) service;//因为我们知道在Myservice中的IBinder对象继承了Binder并实现了IService接口
}
};
this.bindService(intent3, conn, Service.BIND_AUTO_CREATE);
break;
case R.id.but_unbind:
if(conn != null)
this.unbindService(conn);
break;
case R.id.but_func:
if(s != null)
{
s.func();//调用IBinder的方法间接与service通信
}
else
{
Toast.makeText(this,"还没有绑定服务...",0).show();
}
break;
}
}
@Override
protected void onDestroy()//activity销毁时,为避免报错,自动解除绑定service,之所以try起来,是因为service只能被解除绑定一次
{
super.onDestroy();
try
{
if(conn != null)
unbindService(conn);
} catch (Exception e)
{
}
}
}
IService接口:
package com.example.servicedemo2.binder;
public interface IService
{
public void func();
}
运行效果:
六.如何让service与activity进行交互?
package com.example.service;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.widget.Toast;
public class MyService extends Service
{
private MyReceiver receiver = null;
@Override
public IBinder onBind(Intent intent)
{
return null;
}
@Override
public void onCreate()
{
IntentFilter filter = new IntentFilter();
filter.addAction("com.example.broadcast");//监听的动作
receiver = new MyReceiver();
this.registerReceiver(receiver, filter);//注册广播接收者
}
/**
* 服务中的方法
*/
private void serviceMethod()
{
Toast.makeText(getApplicationContext(),"我是服务中的方法...",0).show();
}
@Override
public void onDestroy()
{
if(receiver!=null)
this.unregisterReceiver(receiver);//解除注册
}
public class MyReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
serviceMethod();
}
}
}
测试的activity:
package com.example.myservicedemo3;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.example.service.MyService;
public class MainActivity extends Activity
{
private Button but_send = null;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 开启service服务
Intent intent = new Intent(this,MyService.class);
this.startService(intent);
but_send = (Button) findViewById(R.id.but_send);
but_send.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Intent broadcast = new Intent();
broadcast.setAction("com.example.broadcast");//和service中的receiver接收的action一致
MainActivity.this.sendBroadcast(broadcast);//发广播
}
});
}
}
七.使用AIDL绑定远程服务
package com.example.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class PayService extends Service
{
private static final String TAG = "PayService";
@Override
public IBinder onBind(Intent intent)
{
Log.i(TAG,"绑定了支付服务...");
return new MyBinder();
}
@Override
public boolean onUnbind(Intent intent)
{
Log.i(TAG,"解除绑定支付服务...");
return false;
}
private class MyBinder extends IService.Stub
{
@Override
public void callServiceFunc()
{
pay();
}
}
/**
* 服务内部的支付方法
*/
private void pay()
{
Log.i(TAG,"调用了支付的方法...");
}
}
package com.example.service;
interface IService
{
void callServiceFunc();
}
package com.example.thirdapplication;
import android.app.Activity;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import com.example.service.IService;
import com.example.service.IService.Stub;
/**
* @author Rowand jj
*
*这是第三方的应用,用来远程调用支付服务。
*使用aidl调用远程服务。
* aidl:Android Interface Definition Language
*/
public class MainActivity extends Activity implements OnClickListener
{
private Button but_bind = null;
private Button but_pay = null;
private IService myService = null;
private ServiceConnection conn = null;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
but_bind = (Button) findViewById(R.id.but_bind);
but_pay = (Button) findViewById(R.id.but_pay);
but_bind.setOnClickListener(this);
but_pay.setOnClickListener(this);
}
@Override
public void onClick(View v)
{
switch (v.getId())
{
case R.id.but_bind:
Intent intent = new Intent("com.example.pay");
conn = new ServiceConnection()
{
@Override
public void onServiceDisconnected(ComponentName name)
{
}
@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
myService = Stub.asInterface(service);
}
};
this.bindService(intent, conn, Service.BIND_AUTO_CREATE);
Toast.makeText(this,"绑定成功...", 0).show();
break;
case R.id.but_pay:
try
{
if(myService!=null)
myService.callServiceFunc();
} catch (RemoteException e)
{
e.printStackTrace();
}
break;
}
}
@Override
protected void onDestroy()
{
super.onDestroy();
if(conn != null)
this.unbindService(conn);
}
}
工程截图如下:
八.service与thread的区别?
示例代码打包下载
------------------------------------------------------------------------------------------------------------------------------------------------------
ps.写一篇博客不容易,希望尊重作者的劳动成果,转载请声明出处:http://blog.csdn.net/chdjj/article/details/19333171