该目录为有关Android中Service的学习
服务(Service)是运行在后台且不与用户发生任何交互的Android组件。它可以被任意其他组件开启或停止。当其处于运行状态时,任何组件都可与它进行绑定。服务也可以自行停止。下面给出几个概念性场景,帮助理解什么是服务。
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。
<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)); } }); } }
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键,切换屏幕的方向,音乐仍然照常播放。
1). Thread:Thread 是程序执行的最小单元,它是分配CPU的基本单位。可以用 Thread 来执行一些异步的操作。
2). Service:Service 是android的一种机制,当它运行的时候如果是Local Service,那么对应的 Service 是运行在主进程的 main 线程上的。如:onCreate,onStart 这些函数在被系统调用的时候都是在主进程的 main 线程上运行的。如果是Remote Service,那么对应的 Service 则是运行在独立进程的 main 线程上。因此请不要把 Service 理解成线程,它跟线程半毛钱的关系都没有!