Android Service探究
Service和Activity一样,是android系统四大组件之一,使用前必须和activity一样在androidmanifest中配置。
本地服务的开启和关闭
case R.id.start_service:
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
break;
case R.id.stop_service:
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
onCreate()方法只会在Service第一次被创建的时候调用,而总是用上述方法启动服务,onStartCommand()方法每次都执行。
Service和Activity通信:
上面的方式Activity只是通知Service启动,如果想要更多控制需要用“绑定”的方式
public void startService(View v){
Intent serviceIntent = new Intent(this,ForegroundService.class);
bindService(serviceIntent, conn, Service.BIND_AUTO_CREATE);//关联之后,Service自动创建
}
public void stopService(View v){
unbindService(conn);
}
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName arg0) {
// TODO Auto-generated method stub
System.out.println("method disconn");//unbind()并不会执行这里
}
@Override
public void onServiceConnected(ComponentName arg0, IBinder arg1) {
// TODO Auto-generated method stub
ForegroundService.MyBinder binder = (ForegroundService.MyBinder)arg1;
binder.method1();
System.out.println("method conning");
}
};
混合启动的销毁
如果我们既调用了了startService,又调用了BindService。单独调用StopService只能使服务停止,单独调动unBindService只能解除Service和Activity的关联。一个Service必须要在既没有和任何Activity关联又处理停止状态的时候才会被销毁。
#
容易混淆的地方
本地服务
依附于主进程,在一定程度上节约了资源,因为是在同一个进程因此不需要IPC,也不需要AIDL。binder操作较为简单。当主进程被杀后,服务也会终止。
远程服务
运行在独立的进程(进程名:报名+【android:process】value)。“客户端”进程被杀后,服务仍然在运行,不受其他进程影响,相应的占据一定资源通过AIDL进行IPC。该类服务一般都是系统服务。本地服务在Androidmenifest的配置Service加入
android:process=":DownService“
就变成了远程服务,这个时候再直接bindService就会报错。让Activity与一个远程Service建立关联,就要使用AIDL来进行跨进程通信了(IPC)。
实现步骤:demo1是同一个app下服务运行在不同的进程,两者通信
1 新建*.aidl文件,模板:
package com.example.mainservice;
interface CustomAidl{
int add(int a,int b);
}
2 自定义Service
package com.example.mainservice;
public class CusService extends Service{
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return mBinder;
}
CustomAidl.Stub mBinder = new Stub() {
@Override
public int add(int a, int b) throws RemoteException {
// TODO Auto-generated method stub
return a+b;
}
};
}
3 调用
public void onStartButtonClick(View v){
//Intent service = new Intent(this,CusService.class); //显式的也可以
Intent service = new Intent("com.bj.jack.service");
bindService(service, conn, Service.BIND_AUTO_CREATE);
}
CustomAidl cusAidl;
class ServerConn implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName arg0, IBinder binder) {
// TODO Auto-generated method stub
cusAidl = CustomAidl.Stub.asInterface(binder);
try {
System.out.println("____result:"+cusAidl.add(2, 3));
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
// TODO Auto-generated method stub
}
}
public void onStopButtonClick(View v){
unbindService(conn);
}
4 在androidmenifest的配置
<service
android:name="com.example.mainservice.CusService"
android:process=":remote" >
<intent-filter>
<action android:name="com.bj.jack.service" />
</intent-filter>
</service>
MainActivity和服务属于不同的进程,实现了通信。
实现步骤:demo2,另外一个ClientApp和MainApp的服务交互
1 将CustomAidl.aidl拷贝到ClientApp工程中,一定要放在和原来的包结构相同的包下。
2 执行demo1的调动步骤,确保一点:Intent是用隐式,当然显式的也没法用找不到CusService
- 前台服务
Service绝大多数都是在后台运行的,默默无闻的在后面干活。它的优先级是还不是很高的。当系统出现内存不够的时候,就会回收掉,这个时候就可以考虑使用前台Service。前台Service和普通Service的最大区别在于,它会一直有一个正在运行的图标在系统的状态栏显示,下拉可查看详情,。类似于Noticification。前台服务可以解决两个问题:一是可以尽可能的保障服务不被“干掉”,另外一个是可以在后台执行操作的同时将数据更新到状态栏。
前台服务的创建方式:
public class ForegroundService extends Service{
MyBinder myBinder = new MyBinder();
@SuppressWarnings("deprecation")
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
Notification noitfNotification = new Notification(R.drawable.a5,"who am i",System.currentTimeMillis());
Intent intent = new Intent(this,Show.class);
PendingIntent pending = PendingIntent.getActivity(this, 0, intent, 0);
noitfNotification.setLatestEventInfo(this, "titile", "content", pending);
noitfNotification.contentView = new RemoteViews(getPackageName(), R.layout.activity_main2);
startForeground(1, noitfNotification);
return myBinder;
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
return super.onStartCommand(intent, flags, startId);
}
public class MyBinder extends Binder{
public void method1(){
System.out.println("method1");
}
}
}
- 后台服务
默认创建的服务即是后台服务。
需要注意的地方
- Thread与Service区别
Thread是程序执行的最小单元,是分配CPU的基本单位,可以用Thread来执行一些异步的操作。Service是android的一种机制,如果是Local Service,那么对应的Service是运行在主线程上的;如果Remote Service,它是运行在独立的进程上。
所以Service跟线程是不同的概念。
- 两者的使用场景:
Thread的运行独立于Activity,当Activity结束后,将失去对Thread的引用。另外,无法在多个Activity对通一个Thread进行控制。比如我们需要保持和服务器同步,定时发送心跳包,在Service里面创建、运行并控制Thread,这样任何一个Activity都可以控制同一个Service,系统也也只会创建一个对应的Service的实例
6/3/2015 4:42:04 PM