Android Service详解(1)

Freedie移动互联网研究院原创文章如转载,请注明:转载自博客原文地址:http://www.qinjianping.com/?p=20#content

Service是没有用户界面的,在后台运行的Android Framework核心组件之一。Android支持两种Service:本地Service和远程Service。所谓的“本地Service”是指这种Service只能被当前应用程序访问,而不能被其他应用程序访问。那与之相对的“远程Service”不仅可以被当前的应用程序访问,还可以被不同进程当中的应用程序访问。远程Service通过使用Android Interface Definition Language(AIDL)来实现不同进程当中对于Service的调用。

秘籍一、如何创建一个简单的Service

public class TestService1 extends Service {
	private static final String TAG = "TestService1";
	
	@Override
	public void onCreate() {
		Log.d(TAG, "-->onCreate() method was invoked");
		super.onCreate();
	}
	
	@Override
	public IBinder onBind(Intent intent) {
		Log.d(TAG, "-->onBind() method was invoked");
		return null;
	}

}

首先,定义的Service需要继承android.app.Service,然后需要在项目清单文件当中声明此Service。

 <service android:name="TestService1"></service>

PS:虽然这么一个Service没有任何实际的作用,但是不得不说定义一个Service就是这么的简单。

秘籍二、深入理解Android当中的Service

onCreate()方法是当Service第一次创建时由系统自动回调的一个方法,跟Activity的onCreate()的回调机制类似,主要可以用来做一些在Service启动的时候的初始化的操作。比如,我们可以在onCreate()方法当中启动一个后台线程,在onDestory()方法当中停止线程。调用Service的客户端可以通过两种方式来启动Service,分别为Context.startService()和Context.bindService()方法。注意:一般来讲,通过Context.startService()启动的Service都是本地的Service,而通过Context.bindService()启动的Service都是远程Service,但是也不一定,如果你的应用程序,比如说Activity需要跟本地Service做交互,那么你也只能采用Context.bindService()来启动本地Service。Android为什么提供Service这种机制?主要有两个原因,第一是允许开发者利用Service从而轻松的实现一些后台的任务处理,第二是允许开发者通过使用AIDL来实现进程间的交互。什么时候使用本地Service,什么时候使用远程Service?简单来说,如果某一个Service目的仅仅是为了在当前应用程序当中做一些后台任务,而其他应用程序当中不需要做这些任务的时候,那么这个Service就可以定义为本地Service, 而不用去实现onBind()方法。相反,如果某一个Service()的后台任务,不仅当前应用程序需要,其他应用程序也需要做此中后台任务,那么可以把这个Service定义为远程Service,实现服务的共享。

综上所述:不能仅仅通过客户端的调用方式来判断这个Service是属于本地Service还是远程Service。因为客户端如果需要与本地Service做一定的交互,也只能是通过Context.bindService()来启动服务,我们可以根据应用程序当中是否有相应的AIDL文件来进行判断,如果有相应的AIDL文件,则表明此Service是远程Service。如果没有,则表明此Service为本地Service。

秘籍三、理解本地Service

public class BackgroundService extends Service {
	private NotificationManager notificationMgr;
	
	@Override
	public void onCreate() {
		super.onCreate();
		notificationMgr = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
		displayNotificationMessage("starting Background Services");
		Thread tr = new Thread(new ServiceWorker());
		tr.start();
	}
	
	class ServiceWorker implements Runnable{
		 @Override
		public void run() {
			 //do background processing here
			 //stop when service when done 
			 //BackgroundService.this.stopSelf();
		}
	}
	private void displayNotificationMessage(String message) {
		Notification notification = new Notification(R.drawable.icon, message, System.currentTimeMillis());
		PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);
		notification.setLatestEventInfo(this, "Background Service", message, contentIntent);
		notificationMgr.notify(R.id.app_notification_id, notification);
	}
	
	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}
	
	@Override
	public void onDestroy() {
		super.onDestroy();
		displayNotificationMessage("stopping Background Service");
	}
}

客户端如何调用本地Service:
public class LocaleServiceActivity extends Activity {
	private static final String TAG = "LocaleServiceActivity";
	
	Button mBindBtn, mUnbindBtn;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        Log.d(TAG, "starting service");
    	mBindBtn = (Button)findViewById(R.id.bindButton);
		mUnbindBtn = (Button)findViewById(R.id.stopButton);
		
		mBindBtn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				startService(new Intent(LocaleServiceActivity.this, BackgroundService.class));
			}
		});
		
		mUnbindBtn.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				stopService(new Intent(LocaleServiceActivity.this, BackgroundService.class));
			}
		});
    }
}
如果你还是觉得我写的不够详细 看的不够爽 不要紧我把本地Service源代码的下载地址贴出来 欢迎大家一起讨论学习ALFA DeV工作室希望可以和大家一起进步。

下载地址:
http://download.csdn.net/source/3568186

秘籍四、理解远程Service

1、首先需要定义AIDL文件

定义好AIDL文件之后,eclipse会在gen目录下面自动生成IStockQuoteService.java文件。在这个接口当中定义了一个静态抽象类Stub,这个类继承了android.os.Binder并且实现了IStockQuoteService接口。


2、实现远程Service

public class StockQuoteService extends Service {
	private static final String TAG = "StockQuoteService";
	
	public class StockQuoteServiceImpl extends IStockQuoteService.Stub{

		@Override
		public double getQuote(String ticker) throws RemoteException {
			Log.v(TAG, "getQuote() called for" + ticker);
			return 20.0;
		}
		
	}
	
	@Override
	public void onCreate() {
		Log.v(TAG,"onCreate() called");
		super.onCreate();
	}
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.v(TAG,"onStartCommand() called");
		return super.onStartCommand(intent, flags, startId);
	}
	
	@Override
	public IBinder onBind(Intent intent) {
		return new StockQuoteServiceImpl();
	}
	
	@Override
	public void onDestroy() {
		Log.v(TAG,"onDestory() called");
		super.onDestroy();
	}

}

为了将此Service暴露给其他客户端,我们需要在项目清单文件中加上如下配置:

  <service android:name="StockQuoteService">
	    <intent-filter>
	    	<action android:name="com.freedie.remoteservicedemo.IStockQuoteService"/>
		</intent-filter>
	</service>

3、客户端对远程Service进行调用


需要将aidl文件copy到客户端应用程序当中,当然你需要建立好原先AIDL所在的包名,然后将AIDL文件放在此包名下。

public class MainActivity extends Activity {
	private static final String TAG = "MainActivty";
	
	private Button bindBtn, calBtn, unbindBtn;
	
	private IStockQuoteService stockService = null;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        bindBtn = (Button)findViewById(R.id.bindButton);
        calBtn = (Button)findViewById(R.id.calButton);
        unbindBtn = (Button)findViewById(R.id.unbindButton);
        
        
        
        bindBtn.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				bindService(new Intent(IStockQuoteService.class.getName()), serConn, Context.BIND_AUTO_CREATE);
			}
		});
        
        calBtn.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				calService();
			}
		});
        
        unbindBtn.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				unbindService(serConn);
			}
		});
    }
    
    private void calService() {
    	try{
    		double val = stockService.getQuote("ALFA DeV");
    		Toast.makeText(this, "Value From service is:" + val, Toast.LENGTH_SHORT).show();
    	}catch(RemoteException e){
    		Log.e(TAG, e.getMessage());
    	}
	}

	private ServiceConnection serConn = new ServiceConnection(){

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			Log.v(TAG, "onServiceConnected() callled");
			stockService = IStockQuoteService.Stub.asInterface(service);
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			Log.v(TAG, "onServiceDisconnected() called");
			stockService = null;
		}
    	
    };
}
客户端也写好之后,需要写将远程Service应用程序部署到真机或者模拟器上面,然后将客户端调用程序也部署上去。
单击Bind按钮之后,进行绑定远程Service。单击Cal按钮,界面效果如下:


调用远程服务成功。

本篇博客简单介绍了两种不同的Service,本地服务如何定义,以及客户端如何进行调用,以及远程服务的定义和调用方法。下篇博客,ALFA DeV工作室将会为大家更深入的讲解如何使用Service,在什么情况下使用Service,目的是让大家对Service有个非常清晰地认识,能够在适当场合正确使用Service。


最后如果你还是觉得我写的不够详细 看的不够爽 不要紧我把远程服务源代码的下载地址贴出来 欢迎大家一起讨论学习ALFA DeV工作室希望可以和大家一起进步。

下载地址:
http://download.csdn.net/source/3568196


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值