Android开发历程_13(Service的使用)
Service在android中的地位和activity,只是它没有单独的界面,一般都是在后台运行,主要是用来运行一些消耗时间比较长的任务。我们可以用它来发送intent来更新activity的UI。另外需要注意的是service既不是一个单独的进程,也不是一个单独的线程,它与activity一起在同一个进程中。
关于android的sevice,网上这篇文章对service做了比较详细的介绍,并通过启动音乐播放器的例子来讲解service:http://www.cnblogs.com/allin/archive/2010/05/15/1736458.html
Service的生命周期
既然service和activity一样重要,则和activity类似,它也有自己的生命周期。它的生命周期与启动service的方式不同与不同,比如在activity中启动service时,如果采用的是 activity.startService()启动,则该service的生命周期一般为:
onCreate()->onStart()/onStartCommand()->service running->onDestroy().
如果是activity.bindService()启动,则该service的生命周期为:
onCreate()->onBind()->service running->onUnbind()->onDestrop().
实验部分
本次实验主要是学习怎样在activity中启动一个service,启动的service的生命周期顺序是哪些,然后service通过广播机制向特定的activity传递数据,传送数据当然用的是intent,然后接收到该广播的activity读取intent中的数据,根据读取到的数据来更新activity的UI。
关于怎样通过service广播机制来更新activity的UI,可以阅读网上的这篇文章:http://www.pocketdigi.com/20110303/197.html
需要注意的是service类是继承的android框架中的Service类,程序中需要将写好的service在AndriodManiFest.xml中进行注册,注册方法和activity的注册类似。
本程序的activity中有2个按钮和1个TextView,2个按钮分别用来启动service和停止service,然后在activtiy和service的生命周期函数中各自在后台打印出相关语句,同时为了方便观察,程序也直接将相关语句输出到了textview中。
启动程序后,界面如下:
单击一次start service按钮,然后单击一次end service,再单击一次start service按钮后,界面输出如下:
后台输出如下:
程序主要部分代码和注释(附录有实验工程code下载链接):
MainActivity.java:
package com.example.service; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity { private TextView text = null; private Button start = null; private Button end = null; MyReceiver receiver; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); text = (TextView)findViewById(R.id.text); start = (Button)findViewById(R.id.start); start.setOnClickListener(new StartOnClickListener()); end = (Button)findViewById(R.id.end); end.setOnClickListener(new EndOnClickListener()); System.out.println("Activity onCreate"); text.append("\nActivity onCreate..."); //因为该activity要接收广播消息,所以先顶一个一个接收器对象 //该对象自己实现,是继承BroadcastReceiver的 receiver=new MyReceiver(); //定义一个IntentFilter的对象,来过滤掉一些intent IntentFilter filter = new IntentFilter(); //只接收发送到action为"android.intent.action.MAIN"的intent //"android.intent.action.MAIN"是在MainFest中定义的 filter.addAction("android.intent.action.MAIN"); //启动广播接收器 MainActivity.this.registerReceiver(receiver, filter); } public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); if(bundle.getInt("i") == 1) text.append("\nService onBind..."); else if(bundle.getInt("i") == 2) text.append("\nService onCreate..."); else if(bundle.getInt("i") == 3) text.append("\nService onStartCommand..."); else if(bundle.getInt("i") == 4) text.append("\nService onDestroy..."); } } private class StartOnClickListener implements OnClickListener { public void onClick(View v) { // TODO Auto-generated method stub Intent intent = new Intent(); //跳转到service用startService,以前跳转到activity用的是startactivity intent.setClass(MainActivity.this, FisrtService.class); //启动service startService(intent); } } private class EndOnClickListener implements OnClickListener { public void onClick(View v) { // TODO Auto-generated method stub Intent intent = new Intent(); intent.setClass(MainActivity.this, FisrtService.class); //结束service stopService(intent); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
FirstService.java:
package com.example.service; import android.app.Service; import android.content.Intent; import android.os.IBinder; //从Service类继承而来 public class FisrtService extends Service{ Intent intent = new Intent(); //intent.setAction("android.intent.action.MAIN"); @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub System.out.println("Service onBind"); intent.putExtra("i", 1); //service设置需要接收广播intent的activity intent.setAction("android.intent.action.MAIN"); //service通过广播发送intent sendBroadcast(intent); return null; } @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); System.out.println("Service onCreate"); intent.putExtra("i", 2); intent.setAction("android.intent.action.MAIN"); sendBroadcast(intent); } //onStartCommand与onStart类似,多了一个参数而已 @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub System.out.println("flags---->"+flags); System.out.println("startId---->"+startId); System.out.println("Service onStartCommand"); //不懂为什么这里要重新开一个intent,它的activity才能接收到它 Intent intent1 = new Intent(); intent1.putExtra("i", 3); intent1.setAction("android.intent.action.MAIN"); sendBroadcast(intent1); // //很奇怪为什么这里这样用,在activity中竟然接收不到该intent,一定要重新开一个intent? // intent.putExtra("i", 3); // intent.setAction("android.intent.action.MAIN"); // sendBroadcast(intent); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); System.out.println("Service onDestroy"); intent.putExtra("i", 4); intent.setAction("android.intent.action.MAIN"); sendBroadcast(intent); } }
Activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/text" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello_service" android:layout_alignParentTop="true" /> <Button android:id="@+id/end" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:text="@string/end" /> <Button android:id="@+id/start" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_above="@id/end" android:text="@string/start" /> </RelativeLayout>
AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.service" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/title_activity_main" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".FisrtService"></service> </application> </manifest>
总结:使用service可以在主界面运行的时候也能在后台运行多个服务,并且结合广播机制可以完成一些常见的功能。
附录: