该目录为有关Android中Service的学习
服务(Service)的简单介绍:
服务(Service)是运行在后台且不与用户发生任何交互的Android组件。它可以被任意其他组件开启或停止。当其处于运行状态时,任何组件都可与它进行绑定。服务也可以自行停止。下面给出几个概念性场景,帮助理解什么是服务。
- Activity让用户可以选择一组音乐文件,然后启动一个服务来播放这些文件。播放期间,一个新的Activity被启动并绑定到这个服务之上,允许用户变更乐曲或停止播放。
- Activity启动一个服务向网站上传一组图片,一个新的Activity被启动并绑定到服务上,以确定当前正在上传的文件,并把该图片显示在屏幕上。
- 广播接收器接收到一条消息,消息表明用户拍摄了一张图片,随即启动一个服务以将该图片上传到某网站上。然后广播接收器转入非活动状态,并最终杀死以回收内存。但服务会继续运行,直至上传完成。最后,服务自动停止。
服务(Service)的生命周期:
首先Service有两种状态:启动的和绑定的。
启动的(Started):
绑定的(Bound):
注意事项:
service与activity一样都存在与当前进程的主线程中,所以,一些阻塞UI的操作,比如耗时操作不能放在service里进行,比如另外开启一个线程来处理诸如网络请求的耗时操作。如果在service里进行一些耗CPU和耗时操作,可能会引发ANR警告,这时应用会弹出是强制关闭还是等待的对话框。所以,对service的理解就是和activity平级的,只不过是看不见的,在后台运行的一个组件,这也是为什么和activity同被说为Android的基本组件。
生命周期:
特别注意:
1、你应当知道在调用 bindService 绑定到Service的时候,你就应当保证在某处调用 unbindService 解除绑定(尽管 Activity 被 finish 的时候绑定会自 动解除,并且Service会自动停止);
2、你应当注意 使用 startService 启动服务之后,一定要使用 stopService停止服务,不管你是否使用bindService;
3、同时使用 startService 与 bindService 要注意到,Service 的终止,需要unbindService与stopService同时调用,才能终止 Service,不管 startService 与 bindService 的调用顺序,如果先调用 unbindService 此时服务不会自动终止,再调用 stopService 之后服务才会停止,如果先调用 stopService 此时服务也不会终止,而再调用 unbindService 或者 之前调用 bindService 的 Context 不存在了(如Activity 被 finish 的时候)之后服务才会自动停止;
4、当在旋转手机屏幕的时候,当手机屏幕在“横”“竖”变换时,此时如果你的 Activity 如果会自动旋转的话,旋转其实是 Activity 的重新创建,因此旋转之前的使用 bindService 建立的连接便会断开(Context 不存在了),对应服务的生命周期与上述相同。
5、在 sdk 2.0 及其以后的版本中,对应的 onStart 已经被否决变为了 onStartCommand,不过之前的 onStart 任然有效。这意味着,如果你开发的应用程序用的 sdk 为 2.0 及其以后的版本,那么你应当使用 onStartCommand 而不是 onStart。
Service的简单实例:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="start" />
<Button
android:id="@+id/end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="end" />
</LinearLayout>
两个Button,一个负责开始服务,一个负责关闭服务。
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
Button start, end;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start = (Button) findViewById(R.id.start);
end = (Button) findViewById(R.id.end);
start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startService(new Intent(MainActivity.this,MainServive.class));
}
});
end.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
stopService(new Intent(MainActivity.this,MainServive.class));
}
});
}
}
最后是Service的代码:
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class MainServive extends Service {
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "Service created", Toast.LENGTH_SHORT).show();
Thread initBackground = new Thread(new Runnable() {
@Override
public void run() {
play_music();
Log.i("Did i go to here", "Yes I did");
}
});
initBackground.start();
}
@Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Destoryed", Toast.LENGTH_SHORT).show();
m_mediaPlayer.stop();
}
MediaPlayer m_mediaPlayer;
private void play_music(){
m_mediaPlayer = MediaPlayer.create(this, R.raw.a);
try {
m_mediaPlayer.start();
Log.i("Did i go to here....", "Yes I did....");
Thread.sleep(400);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
最后的效果就是点击Button,会响起一段音乐,而且无论是点击Home键,Back键,切换屏幕的方向,音乐仍然照常播放。
Service和Thread:
1). Thread:Thread 是程序执行的最小单元,它是分配CPU的基本单位。可以用 Thread 来执行一些异步的操作。
2). Service:Service 是android的一种机制,当它运行的时候如果是Local Service,那么对应的 Service 是运行在主进程的 main 线程上的。如:onCreate,onStart 这些函数在被系统调用的时候都是在主进程的 main 线程上运行的。如果是Remote Service,那么对应的 Service 则是运行在独立进程的 main 线程上。因此请不要把 Service 理解成线程,它跟线程半毛钱的关系都没有!