Android开发中,当需要创建在后台运行的程序的时候,就要使用到Service。Service 可以分为有无限生命和有限生命两种。
特别需要注意的是Service跟Activities是不同的(简单来说可以理解为后台与前台的区别),例如,如果需要使用Service的话,
需要调用startService(),从而利用startService()去调用Service中的OnCreate()和onStart()方法来启动一个后台的Service。
Service的开发如下:
1.创建继承自Service的类,并实现相关的方法。
2.在androidmanifest.xml中application中添加service配置。
3.通过intent启动或者关闭 相关的服务
启动一个Service的过程如下:
context.startService() ->onCreate()- >onStart()->Service running
其中onCreate()可以进行一些服务的初始化工作,onStart()则启动服务。
停止一个Service的过程如下:
context.stopService() | ->onDestroy() ->Service stop
各种目录文件的获取资源信息:
/res/xml:
XmlResourceParser xml = getResources().getXml(R.xml.data);
/res/raw
getResources().openRawResource(R.raw.rawtext)
/assets
AssetManager assets = getAssets();
assets.open("data.txt"))
服务的生命周期
部分内容参考自CSDN博客:http://blog.csdn.net/wtao158/archive/2010/01/08/5149721.aspx
有了 Service 类我们如何启动他呢,有两种方法:
• Context.startService()
• Context.bindService()
1. 在同一个应用任何地方调用 startService() 方法就能启动 Service 了,然后系统会回调 Service 类的 onCreate() 以及 onStart() 方法。这样启动的 Service 会一直运行在后台,直到 Context.stopService() 或者 selfStop() 方法被调用。另外如果一个 Service 已经被启动,其他代码再试图调用 startService() 方法,是不会执行 onCreate() 的,但会重新执行一次 onStart() 。
2. 另外一种 bindService() 方法的意思是,把这个 Service 和调用 Service 的客户类绑起来,如果调用这个客户类被销毁,Service 也会被销毁。用这个方法的一个好处是,bindService() 方法执行后 Service 会回调上边提到的 onBind() 方发,你可以从这里返回一个实现了 IBind 接口的类,在客户端操作这个类就能和这个服务通信了,比如得到 Service 运行的状态或其他操作。如果 Service 还没有运行,使用这个方法启动 Service 就会 onCreate() 方法而不会调用 onStart()。
总结:
1. startService()的目的是回调onStart()方法,onCreate() 方法是在Service不存在的时候调用的,如果Service存在(例如之前调用了bindService,那么Service的onCreate方法已经调用了)那么startService()将跳过onCreate() 方法。
2. bindService()目的是回调onBind()方法,它的作用是在Service和调用者之间建立一个桥梁,并不负责更多的工作(例如一个Service需要连接服务器的操作),一般使用bindService来绑定到一个现有的Service(即通过StartService启动的服务)。
由于Service 的onStart()方法只有在startService()启动Service的情况下才调用,故使用onStart()的时候要注意这点。
与 Service 通信并且让它持续运行
如果我们想保持和 Service 的通信,又不想让 Service 随着 Activity 退出而退出呢?你可以先 startService() 然后再 bindService() 。当你不需要绑定的时候就执行 unbindService() 方法,执行这个方法只会触发 Service 的 onUnbind() 而不会把这个 Service 销毁。这样就可以既保持和 Service 的通信,也不会随着 Activity 销毁而销毁了。
提高 Service 优先级
Android 系统对于内存管理有自己的一套方法,为了保障系统有序稳定的运信,系统内部会自动分配,控制程序的内存使用。当系统觉得当前的资源非常有限的时候,为了保 证一些优先级高的程序能运行,就会杀掉一些他认为不重要的程序或者服务来释放内存。这样就能保证真正对用户有用的程序仍然再运行。如果你的 Service 碰上了这种情况,多半会先被杀掉。但如果你增加 Service 的优先级就能让他多留一会,我们可以用 setForeground(true) 来设置 Service 的优先级。
为什么是 foreground ? 默认启动的 Service 是被标记为 background,当前运行的 Activity 一般被标记为 foreground,也就是说你给 Service 设置了 foreground 那么他就和正在运行的 Activity 类似优先级得到了一定的提高。当让这并不能保证你得 Service 永远不被杀掉,只是提高了他的优先级。
摘自网络其他资料:关于Service生命周
Android Service生命周期与Activity生命周期是相似的,但是也存在一些细节上也存在着重要的不同:
onCreate和onStart是不同的
通过从客户端调用Context.startService(Intent)方法我们可以启动一个服务。如果这个服务还没有运行,Android将启动它并且在onCreate方法之后调用它的onStart方法。如果这个服务已经在运行,那么它的onStart方法将被新的Intent再次调用。所以对于单个运行的Service它的onStart方法被反复调用是完全可能的并且是很正常的。
onResume、onPause以及onStop是不需要的
回调一个服务通常是没有用户界面的,所以我们也就不需要onPause、onResume或者onStop方法了。无论何时一个运行中的Service它总是在后台运行。
onBind
如果一个客户端需要持久的连接到一个服务,那么他可以调用Context.bindService方法。如果这个服务没有运行方法将通过调用onCreate方法去创建这个服务但并不调用onStart方法来启动它。相反,onBind方法将被客户端的Intent调用,并且它返回一个IBind对象以便客户端稍后可以调用这个服务。同一服务被客户端同时启动和绑定是很正常的。
onDestroy
与Activity一样,当一个服务被结束是onDestroy方法将会被调用。当没有客户端启动或绑定到一个服务时Android将终结这个服务。与很多Activity时的情况一样,当内存很低的时候Android也可能会终结一个服务。如果这种情况发生,Android也可能在内存够用的时候尝试启动被终止的服务,所以你的服务必须为重启持久保存信息,并且最好在onStart方法内来做。
在android中Activity负责前台界面展示,service负责后台的需要长期运行的任务。Activity和Service之间的通信主要由IBinder负责。在需要和Service通信的Activity中实现ServiceConnection接口,并且实现其中的onServiceConnected和onServiceDisconnected方法。然后在这个Activity中还要通过如下代码绑定服务:
- Intent intent = new Intent().setClass( this , IHRService.class );
- bindService( intent , this , Context.BIND_AUTO_CREATE );
当调用bindService方法后就会回调Activity的onServiceConnected,在这个方法中会向Activity中传递一个IBinder的实例,Acitity需要保存这个实例。代码如下:
- public void onServiceConnected( ComponentName inName , IBinder serviceBinder) {
- if ( inName.getShortClassName().endsWith( "IHRService" ) ) {
- try {
- this.serviceBinder= serviceBinder;
- mService = ( (IHRService.MyBinder) serviceBinder).getService();
- //mTracker = mService.mConfiguration.mTracker;
- } catch (Exception e) {}
- }
- }
在Service中需要创建一个实现IBinder的内部类(这个内部类不一定在Service中实现,但必须在Service中创建它)。
- public class MyBinder extends Binder {
- //此方法是为了可以在Acitity中获得服务的实例
- public IHRService getService() {
- return IHRService.this;
- }
- //这个方法主要是接收Activity发向服务的消息,data为发送消息时向服务传入的对象,replay是由服务返回的对象
- public boolean onTransact( int code , Parcel data , Parcel reply , int flags ) {
- //called when client calls transact on returned Binder
- return handleTransactions( code , data , reply , flags );
- }
- }
然后在Service中创建这个类的实例:
- public IBinder onBind( Intent intent ) {
- IBinder result = null;
- if ( null == result ) result = new MyBinder() ;
- return result;
- }
这时候如果Activity向服务发送消息,就可以调用如下代码向服务端发送消息:
- inSend = Parcel.obtain();
- serviceBinder.transact( inCode , inSend , null , IBinder.FLAG_ONEWAY );
这种方式是只向服务端发送消息,没有返回值的。如果需要从服务端返回某些值则可用如下代码:
- result = Parcel.obtain();
- serviceBinder.transact( inCode , inSend , result , 0 );
- return result;
发送消息后IBinder接口中的onTransact将会被调用。在服务中如果有结果返回(比如下载数据)则将结果写入到result参数中。在Activity中从result中读取服务执行的结果。
上面只是描述了如何由Acitity向Service发送消息,如果Service向Activity发送消息则可借助于BroadcastReceiver实现,BroadcastReceiver比较简单,前面在将Service中已有提及。
android service使用实例:
package com.etrip.srvs;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
/**
*
实例:
接下来的实例是一个利用后台服务播放音乐的小例子,点击start运行服务,点击stop停止服务。
*
*
* @author longgangbai
*/
public class AndroidServicesActivity extends Activity implements OnClickListener {
private static final String TAG = "ServicesDemo";
Button buttonStart, buttonStop;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
buttonStart = (Button) findViewById(R.id.buttonStart);
buttonStop = (Button) findViewById(R.id.buttonStop);
buttonStart.setOnClickListener(this);
buttonStop.setOnClickListener(this);
}
public void onClick(View src) {
switch (src.getId()) {
case R.id.buttonStart:
Log.d(TAG, "onClick: starting srvice");
startService(new Intent(this, MyService.class));
break;
case R.id.buttonStop:
Log.d(TAG, "onClick: stopping srvice");
stopService(new Intent(this, MyService.class));
break;
}
}
}
service的实现:
package com.etrip.srvs;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
/**
*
* Service的学习
*
*
* @author longgangbai
*/
public class MyService extends Service {
private static final String TAG = "MyService";
MediaPlayer player;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
player = MediaPlayer.create(this, R.raw.baby);//运行例子是,需要替换音乐的名称
player.setLooping(false); // Set looping
}
@Override
public void onDestroy() {
Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
player.stop();
}
@Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
player.start();
}
}
图片翻转:
package com.easyway.andorid.hello;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout.LayoutParams;
/**
* Android实现图片的缩放功能
* @author longgangbai
* @date 2010-5-24
* @version 1.0
* @since JDK6.0
*/
public class ImageViewAndorid extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//设置程序的标题
setTitle("缩放和旋转图片");
//实例化LinearLayout类的对象lly
LinearLayout lly=new LinearLayout(this);
//获取图片的信息 这里用的是icon.png ,图片存放的位置在res/drawable下,
//同时这里还方有itfunz.bmp,这就是应用程序的图标
Bitmap bmpOrg=BitmapFactory.decodeResource(getResources(), R.drawable.icon);
//获取图片的原始的大小
int width=bmpOrg.getWidth();
int height=bmpOrg.getHeight();
int newWidth=400;
int newheight=400;
//定义缩放的高和宽的尺寸
float sw=((float)newWidth)/width;
float sh=((float)newheight)/height;
//创建操作图片的用的Matrix对象
Matrix matrix=new Matrix();
matrix.postScale(sw,sh);
//缩放图片的动作
matrix.postRotate(30);
//旋转30*
Bitmap resizeBitmap=Bitmap.createBitmap(bmpOrg,0,0,width,height,matrix,true);
//创建一个新的图片
BitmapDrawable bmp=new BitmapDrawable(resizeBitmap);
//创建Bitmap转换为Drawable对象,使其可以使用在ImageView和ImageButton中
ImageView imageView=new ImageView(this);
//创建ImageView的对象
imageView.setImageDrawable(bmp);
//将图片设置到中间
imageView.setScaleType(ScaleType.CENTER);
//将图片填充之整个视图
lly.addView(imageView, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
//添加ImageView到布局模板中
setContentView(lly);
}
}