代码改变世界

[原创]关于Android Service的示例编程 附源码

2012-06-24 15:08  和尚释然  阅读(1448)  评论(0编辑  收藏  举报
关于Android Service的示例编程
一.什么是Android Service
大家知道如果要让Android程序在退出时还需要继续运行一些应用时,例如后台音乐播放,后台数据上传和下载等应用.这个时候可以使用Android Service来实现.网上有很多关于Android Service的介绍,我想最权威的应该是Android API文档的解释.
服务是运行在后台的一个程序组件,而且没有与用户交互接口.其他应用程序可以启动一个服务,而且服务可以继续在后台运行即使用户已经切换到其他应用程序.另外,程序还可以绑定一个服务与它交互,甚至还是进行IPC(Interprocess Communication).例如,服务可能需要处理网路传输,播放音乐,I/O操作,或者与一个内容提供者交互.所有的这些都是来自后台.

二.Android Service的实现
服务主要有以下两种形式:
1. Start
通过调用应用程序组件(例如Activity)的startService()方法来启动一个服务.一旦启动,服务就会在后台一直运行,即使应用程序组件此时被关闭.通常,已经启动的服务会处理一些单一功能,并且也不需要返回结果给调用者.例如,在网络上下载或上传文件.当服务的工作处理结束,才会自己关闭服务.
2. Bound
通过调用应用程序组件的bindService()方法来绑定一个服务.已绑定的服务会提供一个客户端-服务端交互接口.该接口主要用来与应用程序交互,发送请求,获取结果,甚至通过IPC来访问进程.只要一个程序组件绑定服务就会运行绑定服务,多个应用程序组件可以同时时间绑定一个服务.当所有的应用程序组件都解除绑定,该绑定服务器就会被销毁.
下面我们分别对"Started Service"和"Bound Servie"作一个介绍.

.创建Started Service
我觉得通过一个实例来介绍比文字说明更能说明知识点.同时也让开发者清楚地了解到创建一个"Started Service"的开发流程.实例是一个利用后台服务播放音乐的Demo,点击Start运行服务,点击Stop停止服务.

1. 创建一个"Android Project"名为"StatredServiceDemo".
2.创建界面元素.
3. 在Manifest里面声明服务,添加MyService声明.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.gel.service"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk android:minSdkVersion="10" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:label="@string/app_name"
            android:name=".MainActivity" >
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:enabled="true" android:name=".MyService" />
    </application>
</manifest>
4. 添加一个MyService类.
实现代码:
public class MyService extends Service {
private static final String TAG = "MyService";
MediaPlayer player;

@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}

@Override
public void onCreate() {
Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.i(TAG, "onCreate");
player = MediaPlayer.create(this, R.raw.ann);
player.setLooping(false);
super.onCreate();
}

@Override
public void onDestroy() {
Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
Log.i(TAG, "onDestroy");
player.stop();
super.onDestroy();
}

@Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.i(TAG, "onStart");
player.start();
}
}
5.MainActivity代码实现
public class MainActivity extends Activity implements OnClickListener {
private static final String TAG = "ServiceDemo";
Button buttonStart;
Button buttonStop;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

/*
 * TextView tv = (TextView)findViewById(R.id.tvTemp); tv.setText("测试");
 */

buttonStart = (Button) findViewById(R.id.btnStart);
buttonStop = (Button) findViewById(R.id.btnStop);

buttonStart.setOnClickListener(this);
buttonStop.setOnClickListener(this);
}

public void onClick(View src) {
switch (src.getId()) {
case R.id.btnStart:
Log.d(TAG, "onClick: starting srvice");
startService(new Intent(this, MyService.class));
break;
case R.id.btnStop:
Log.d(TAG, "onClick: stopping srvice");
stopService(new Intent(this, MyService.class));
break;
}
}
}
6.最后来看看运行效果.
日志输出:
注意:
从日志中我们可以看出
启动一个Service的过程如下:
context.startService()  ->onCreate()  ->onStart()->Service running
停止一个Service的过程如下:
context.stopService()  ->onDestroy() ->Service stop
四.创建Bound Service
Bound Service的创建是通过应用程序组件调用bindService()方法建立的.主要用于长时间连接应用.通常不允许通过调用startService()方法来启动.
创建一个Bound Service必须实现"onBind()"回调方法返回IBinder对象.IBinder用来定义与服务交互的接口.其他程序组件调用bindService()方法取得该接口同时可以调用服务提供的方法.

1. 创建一个Android Project名为"BoundServiceDemo".
 
2. 创建界面元素
3. 新建一个MyService类
MyService代码:
public class MyService extends Service {

// 定义个一个Tag标签
private static final String TAG = "MyService";
// 这里定义吧一个Binder类,用在onBind()有方法里,这样Activity那边可以获取到
private MyBinder mBinder = new MyBinder();

@Override
public IBinder onBind(Intent intent) {
Log.e(TAG, "Start IBinder!");
return mBinder;
}

@Override
public void onCreate() {
Log.e(TAG, "Start onCreate!");
super.onCreate();
}

@Override
public void onStart(Intent intent, int startId) {
Log.e(TAG, "Start onStart!");
super.onStart(intent, startId);
}

@Override
public void onDestroy() {
Log.e(TAG, "Start onDestroy!");
super.onDestroy();
}

@Override
public boolean onUnbind(Intent intent) {
Log.e(TAG, "Start onUnbind!");
return super.onUnbind(intent);
}

// 这里我写了一个获取当前时间的函数,不过没有格式化就先这么着吧
public String getSystemTime() {
Time t = new Time();
t.setToNow();
return t.toString();
}

public class MyBinder extends Binder {
MyService getService() {
return MyService.this;
}
}
}
4.  在Manifest里面声明服务,添加MyService声明.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.gel.service"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk android:minSdkVersion="10" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:label="@string/app_name"
            android:name=".MainActivity" >
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name=".MyService" android:exported="true"></service> 
    </application>
</manifest>
5. MainActivity代码实现
public class MainActivity extends Activity implements OnClickListener {

private MyService mMyService;
private TextView mTextView;
private Button bindServiceButton;
private Button unbindServiceButton;
private Context mContext;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setupViews();
}

private ServiceConnection mServiceConnection = new ServiceConnection() {
// 当我bindService时,让TextView显示MyService里getSystemTime()方法的返回值
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
mMyService = ((MyService.MyBinder) service).getService();
mTextView.setText("来自MyService的系统时间:"
+ mMyService.getSystemTime());
}

public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub

}
};

public void setupViews() {

mContext = MainActivity.this;
mTextView = (TextView)findViewById(R.id.tvInfo);

bindServiceButton = (Button) findViewById(R.id.btnStart);
unbindServiceButton = (Button) findViewById(R.id.btnStop);

bindServiceButton.setOnClickListener(this);
unbindServiceButton.setOnClickListener(this);
}

public void onClick(View v) {
// TODO Auto-generated method stub
if (v == bindServiceButton) {
Intent i = new Intent();
i.setClass(MainActivity.this, MyService.class);
mContext.bindService(i, mServiceConnection, BIND_AUTO_CREATE);
} else {
mContext.unbindService(mServiceConnection);
}
}

}
6. 运行结果.

日志输出:
下面这张流程图很好的诠释了"startService()"和"bindService()"两个方法调用的生命周期.
源码地址:
参考: