Android开发学习之Service详解一

Android之Service服务
                   
Service:运行在后台提供某种服务,并可以和其他组件进行交互,不可见没有界面,级别和Activity差不多。
         可以启动一个Service来播放音乐,或者记录地理位置信息的改变,或者启动一个服务来运行并一直监听某种动作。
         它主要用于在后台处理一些耗时的逻辑,或者去执行某些需要长期运行的任务。必要的时候我们甚至可以在程序退出的情况下,让Service在后台继续保持运行状态。
         其它的组件可以启动一个Service,即使用户切换到另外一个应用程序后,这个Service还是会一直在后台运行,
         另外,应用程序还可以绑定到一个Service然后使用进程间通信(IPC)方式与Service之间发生交互。例如一个Service可以处理网络事物,播放音乐,读写文件或者读写ContentProvider,所以这些都在后台运行。
         
注意:    Service和其它组件一样,都运行在主线程里,因此不能用它来做耗时的请求或操作,否则会造成用户界面阻塞。

          可以在Service中开启一个线程,在开启的线程中做耗时的各类操作,如下载等.


如果打算采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,

  接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,

  但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。

  如果打算采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,

  接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,

  接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,

  多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。

  如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()-->onDestroy()方法.




启动Service方式:  
    Context.startService()
    Context.bindService();
    
    1.startService
    
    使用StartService()方法启动服务后,调用者与服务之间没有关联。调用者直接退出而没有调用stopService,Service会一直在后台运行,下次调用者再起来仍然可以。
      1.启动流程:
          如果调用前服务没有被创建  onCreate()  -- > onStart()
          如果调用前服务已被创建 , 多次调用startService只会引起onStart()方法被多次调用
      2.结束方式:
          只能调用Context.stopService()结束服务,系统会自动调用到onDestroy()方法
    
    2.bindService
    
    使用bindService()方法启动服务,调用者与服务绑定在一起了,调用者一旦退出,服务也就自动终止
      1.启动流程:
          如果调用前服务没被创建, onCreate() -- > onStart()
          如果已被创建但没有被绑定, 一起 onBind()
          如果服务已被绑定, 多次调用bindService()不会引起onCreate()和onBind()被多次调用
      2.结束方式:
          调用者退出,系统会自动调用服务到 onUnbind() -- > onDestroy()方法
          如果调用者希望与正在绑定的服务解除绑定,可以调用Context.unbindService(),该方法会导致系统调用服务的onUnbind() -- > onDestroy()方法
          
注意:
    1.如果第一次调用 startService(),系统会onCreate() -- > onStart ();此时调用bindService, 只会onBind();
    如果第一次调用bindService(), 系统会onCreate()->onBind();此时调用startService, 只会onStart();
    2)如果start和bind都调用了, 那么一旦服务被绑定(只要成功调用了bindService, 不管是先start后bind还是后bind先start), 
    就必须调用unbindService和stopService(先unbindService(导致onUnbind())再stopService(导致onDestroy()), 
    或者先stopService再unbindService(导致onUnbind()->onDestroy())都行)才能终止服务。


2.Service生命周期
    Service的生命周期并不像Activity那么复杂,它只继承了onCreate(),onStart(),onDestroy()三个方法,
    当第一次启动Service时,先后调用了onCreate(),onStart()这两个方法,当停止Service时,则执行onDestroy()方法,
    这里需要注意的是,如果Service已经启动了,当我们再次启动Service时,不会在执行onCreate()方法,而是直接执行onStart()方法。


要启动Service有两种方法,分别是Contex.startService(),这种情况下可以调用Context.stopService()来结束服务;另外一种方法是Context.bindService(),这种情况下要调用Context.unbindService()来结束服务,并且多个客户程序都可以bind同一个服务。这两种方法并不是独立的,例如我们可以使用startService()来启动一个在后台播放音乐的服务,这可以通过一个Intent对象来实现,但是当我们想控制音乐的播放或者获取当前歌曲的信息时就需要使用一个Activity通过bindService()方法来同Service建立联系,当一个Service有程序bind的时候即使调用stopService()方法也不会停止服务。具体的生命周期如下图所示:



     
     对于service可以通过在生命周期的方法来监视服务的状态,通过startService()方面启动的服务主要有3个pulbic方法可以实现,其中onStart()方法是其所独有的:
             void onCreate() 
             void onStart(Intent intent) 
             void onDestroy()
     通过bindService()方法启动的服务则可以通过3个额外的方法来监视其状态,分别是:
              IBinder onBind(Intent intent) 
              boolean onUnbind(Intent intent) 
              void onRebind(Intent intent)
     要终止服务可以通过stopService()或者stopSelf()方法,需要注意的是不管服务启动了多少次,一旦调用了这两个方法都会终止服务的运行。




二.Service的启动方式
Service的有两种启动方式:Context.startService()和Context.bindService(),这两种方式对Service生命周期的影响是不同的。
 
1.Context.startService()方式启动
 
①Context.startService()方式的生命周期: 
启动时,startService –> onCreate() –> onStart()
停止时,stopService –> onDestroy()
如果调用者直接退出而没有停止Service,则Service 会一直在后台运行
 
Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,
接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法
并不会导致多次创建服务,但会导致多次调用onStart()方法。采用startService()方法启动的服务,
只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。
②Context.startService()方式启动 Service的方法:

MainActivity.java
public class MainActivity extends ActionBarActivity {


private Button button1;
private Button button2;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
button1 = (Button) findViewById(R.id.button1);
button2 = (Button) findViewById(R.id.button2);
button1.setOnClickListener(new buttonOnClickListener());
button2.setOnClickListener(new buttonOnClickListener());
}


//button监听器
private class buttonOnClickListener implements OnClickListener{


@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, ServiceDemo1.class); 
switch (v.getId()) {
case R.id.button1:
startService(intent);
break;
            case R.id.button2:
stopService(intent);
break;


default:
break;
}

}
}
}




ServiceDemo1.java
public class ServiceDemo1 extends Service {


private static final String TAG="test";

@Override
public void onCreate() {
Log.i(TAG, "Service onCreate --->");
super.onCreate();
}
@Override
public void onStart(Intent intent, int startId) {
Log.i(TAG, "Service onStart--->");  
        super.onStart(intent, startId); 
};

@Override
public void onDestroy() {
Log.i(TAG, "Service onDestroy--->");  
super.onDestroy();
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
}


在AndroidManifest.xml中注册服务
<service android:name=".ServiceDemo1">
<intent-filter >
     <action android:name="android.intent.action.MAIN" /> 
    <category android:name="android.intent.category.LAUNCHER" /> 
</intent-filter>
</service>



效果图:

当点击按钮时,先后执行了Service中onCreate()->onStart()这两个方法,LogCat显示如下:

当点击 按钮时,Service则执行了onDestroy()方法,LogCat显示如下:




2.Context.bindService()方式启动


①Context.bindService()方式的生命周期:
绑定时, bindService -- > onCreate() -- > onBind();
调用者退出时,即解除绑定时, unbindService -- > onUnbind() -- > onDestroy()


用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,
接着调用onBind()方法。这时调用者和服务绑定在一起,调用者退出,系统会调用服务的onUnbind()方法,接着调用onDestroy()方法。
如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法,并不会导致多次创建服务及绑定(
也就是说onCreate()和onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,
调用该方法也会导致系统调用服务的onUnbind() -- >onDestroy()方法。


②Context.bindService()方式启动 Service的方法:
绑定Service需要三个参数:bindService(intent, conn, Service.BIND_AUTO_CREATE);
第一个:Intent对象
第二个:ServiceConnection对象,创建该对象要实现它的onServiceConnected()onServiceDisconnected()来判断连接成功或者断开连接

第三个:如何创建Service,一般指绑定的时候自动创建

应用实例:

package com.example.servicedemo1;

import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.os.Build;

public class BindServiceActivity extends ActionBarActivity {

	// 声明Button  
    private Button startBtn,stopBtn,bindBtn,unbindBtn;  
    
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_bind_service);

		if (savedInstanceState == null) {
			getSupportFragmentManager().beginTransaction()
					.add(R.id.container, new PlaceholderFragment()).commit();
		}
		
		// 实例化Button  
        startBtn = (Button)findViewById(R.id.startBtn1);  
        stopBtn = (Button)findViewById(R.id.stopBtn2);  
        bindBtn = (Button)findViewById(R.id.bindBtn3);  
        unbindBtn = (Button)findViewById(R.id.unbindBtn4); 
        startBtn.setOnClickListener(new buttonOnClickListener());
        stopBtn.setOnClickListener(new buttonOnClickListener());
        bindBtn.setOnClickListener(new buttonOnClickListener());
        unbindBtn.setOnClickListener(new buttonOnClickListener());
	}

	 // 连接对象  
	   private ServiceConnection conn = new ServiceConnection() {  
	        @Override 
	        public void onServiceConnected(ComponentName name, IBinder service) {  
	            Log.i("Service", "连接成功!");  
	        }  
	        @Override 
	        public void onServiceDisconnected(ComponentName name) {  
	            Log.i("Service", "断开连接!");  
	        }  
	    }; 
	    
	//button监听器
		private class buttonOnClickListener implements OnClickListener{

			@Override
			public void onClick(View v) {
				Intent intent = new Intent(BindServiceActivity.this, ServiceDemo1.class); 
				switch (v.getId()) {
				case R.id.startBtn1:
					startService(intent);
					break;
	            case R.id.stopBtn2:
					stopService(intent);
					break;
	            case R.id.bindBtn3:
	            	bindService(intent, conn, Service.BIND_AUTO_CREATE);
					break;
	            case R.id.unbindBtn4:
					unbindService(conn);
	            	break;
					
				default:
					break;
				}
				
			}
			
		}
		
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {

		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.bind, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle action bar item clicks here. The action bar will
		// automatically handle clicks on the Home/Up button, so long
		// as you specify a parent activity in AndroidManifest.xml.
		int id = item.getItemId();
		if (id == R.id.action_settings) {
			return true;
		}
		return super.onOptionsItemSelected(item);
	}

	/**
	 * A placeholder fragment containing a simple view.
	 */
	public static class PlaceholderFragment extends Fragment {

		public PlaceholderFragment() {
		}

		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container,
				Bundle savedInstanceState) {
			View rootView = inflater.inflate(R.layout.fragment_bind, container,
					false);
			return rootView;
		}
	}

}


ServiceDemo1.java

package com.example.servicedemo1;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class ServiceDemo1 extends Service {

	private static final String TAG="test";
	
	@Override
	public void onCreate() {
		Log.i(TAG, "Service onCreate --->");
		super.onCreate();
	}
	@Override
	public void onStart(Intent intent, int startId) {
		Log.i(TAG, "Service onStart--->");  
        super.onStart(intent, startId); 
	};
	
	@Override
	public void onDestroy() {
		Log.i(TAG, "Service onDestroy--->");  
		super.onDestroy();
	}
	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}
	@Override
	public boolean onUnbind(Intent intent) {
		Log.i(TAG, "Service onUnbind--->"); 
		return super.onUnbind(intent);
	}

}

效果图:

当点击按钮时,先后执行了Service中onCreate()->onStart()这两个方法,LogCat显示如下:

 

当点击按钮,则Service执行了onUnbind()方法,LogCat显示如下:

 

当点击按钮,则Service执行了onUnbind()方法,LogCat显示如下:



拓展知识(进程和生命周期)

Android操作系统尝试尽可能长时间的保持应用的进程,但当可用内存很低时最终要移走一部分进程。怎样确定那些程序可以运行,那些要被销毁,Android让每一个进程在一个重要级的基础上运行,重要级低的进程最有可能被淘汰,一共有5级,下面这个列表就是按照重要性排列的:

1 一个前台进程显示的是用户此时需要处理和显示的。下列的条件有任何一个成立,这个进程都被认为是在前台运行的。
        a 与用户正发生交互的。
        b 它控制一个与用户交互的必须的基本的服务。
        c 有一个正在调用生命周期的回调函数的service(如onCreate()、onStar()、onDestroy())
        d 它有一个正在运行onReceive()方法的广播接收对象。
只有少数的前台进程可以在任何给定的时间内运行,销毁他们是系统万不得已的、最后的选择——当内存不够系统继续运行下去时。通常,在这一点上,设备已经达到了内存分页状态,所以杀掉一些前台进程来保证能够响应用户的需求。

2 一个可用进程没有任何前台组件,但它仍然可以影响到用户的界面。下面两种情况发生时,可以称该进程为可用进程。
        它是一个非前台的activity,但对用户仍然可用(onPause()方法已经被调用)这是可能发生的,例如:前台的activity是一个允许上一个activity可见的对话框,即当前activity半透明,能看到前一个activity的界面,它是一个服务于可用activity的服务。

3 一个服务进程是一个通过调用startService()方法启动的服务,并且不属于前两种情况。尽管服务进程没有直接被用户看到,但他们确实是用户所关心的,比如后台播放音乐或网络下载数据。所以系统保证他们的运行,直到不能保证所有的前台可见程序都正常运行时才会终止他们。

4 一个后台进程就是一个非当前正在运行的activity(activity的onStop()方法已经被调用),他们不会对用户体验造成直接的影响,当没有足够内存来运行前台可见程序时,他们将会被终止。通常,后台进程会有很多个在运行,所以他们维护一个LRU最近使用程序列表来保证经常运行的activity能最后一个被终止。如果一个activity正确的实现了生命周期的方法,并且保存它当前状态,杀死这些进程将不会影响到用户体验。

5 一个空线程没有运行任何可用应用程序组,保留他们的唯一原因是为了设立一个缓存机制,来加快组件启动的时间。系统经常杀死这些内存来平衡系统的整个系统的资源,进程缓存和基本核心缓存之间的资源。
Android把进程里优先级最高的activity或服务,作为这个进程的优先级。例如,一个进程拥有一个服务和一个可见的activity,那么这个进程将会被定义为可见进程,而不是服务进程。

此外,如果别的进程依赖某一个进程的话,那么被依赖的进程会提高优先级。一个进程服务于另一个进程,那么提供服务的进程不会低于获得服务的进程。例如,如果进程A的一个内容提供商服务于进程B的一个客户端,或者进程A的一个service被进程B的一个组件绑定,那么进程A至少拥有和进程B一样的优先级,或者更高。

因为一个运行服务的进程的优先级高于运行后台activity的进程,一个activity会准备一个长时间运行的操作来启动一个服务,而不是启动一个线程–尤其是这个操作可能会拖垮这个activity。例如后台播放音乐的同时,通过照相机向服务器发送一张照片,启动一个服务会保证这个操作至少运行在service 进程的优先级下,无论这个activity发生了什么,广播接收者应该作为一个空服务而不是简单的把耗时的操作单独放在一个线程里。



Android服务分类


Android 支持两种服务类型的服务:本地服务和远程服务。本地服务无法供在设备上运行其他应用程序访问。一般而言,这些服务类型仅支持承载该服务的应用程序。而对于远程服务,除了可以承载服务的应用程序访问,还可以从其他应用程序访问。远程服务使用 AIDL(Android Interface Definition Language, Android接口定义语言)向客户端定义其自身。 

Android 中的服务 
通过查看 android.app.Service的公共方法,我们可以更深入地理解服务的概念。 
Application getApplication(); 
Abstract IBinder onBind(Intent intent); 
void onConfigurationChanged(Configuration newConfig); 
void onCreate(); 
void onDestroy(); 
void onLowMemory(); 
void onRebind(Intent intent); 
void onStart(Intent intent, int startId); 
boolean onUnbind(Intent intent); 
final void setForeground(Boolean isForeground); 
final void stopSelf(); 
final void stopSelf(int startId); 
final boolean stopSelfResult(int startId); 

      getApplication()方法返回实现服务的应用程序。onBind()方法为在同一设备上运行的外部应用程序提供一个接口来与服务通信,此方法在远程服务中特别重要。onConfigurationChanged();支持服务在设备配置更改时重新配置自身。 
    
   系统在首次创建服务时调用onCreate(),然后才调用onStart()。此过程类似创建一个Activity的过程,在启动时执行一次初始化。例如,如果创建后台线程,可以在onCreate()方法中进行,在确保在onDestroy()中停止该线程。系统调用 onCreate(),然后调用 onStart(), 最后在关闭服务时调用 onDestroy()。onDestroy()方法为服务提供了一种机制,在关闭之前执行最后的清理。 

   请注意,onStart()、onCreate()、和 onDestroy()都是由系统调用的,不应该直接调用它们。而且,如果在服务类中重写任何on*()方法,请确保从这些方法调用了超类的方法版本。stopSelf()的各种版本为应用程序提供了一种机制来停止服务。客户端也可以调用 Context.stopService()来停止服务。 

    Android支持服务的概念有2个原因。第一,简化后台任务的实施,这种服务也就是本地服务;第二,在同一设备上运行的应用程序之间执行进程通信,这种服务也就是远程服务。本地服务与远程服务的一些重要区别。具体来讲,如果服务完全只供同一进程中的组件使用(以运行后台任务),那么客户端必须调用 Context.startService()来启动该服务。这种类型的服务为本地服务,因为它的一般用途是运行承载服务的应用程序的后台任务。如果服务支持onBind()方法,那么它属于远程服务,可通过进程间通信 (Context.bindService())进程调用。我们也将远程服务称为AIDL 支持服务,因为客户端使用 AIDL 与服务通信。 
   
   尽管 android.app.Service接口同时支持本地服务和远程服务,但并不建议提供一种服务的实现同时支持两种类型。因为每种服务的类型都有预定义的生命周期,将两种服务合并在一起可能导致错误(尽管允许这么做)。 

  说明:Android中的第二种服务类型有多种叫法:远程服务、AIDL服务、外部服务和RPC服务。这些名称都是指向同一类型的服务----------可供在设备上运行的其他应用程序远程访问的服务。 

本地服务 
   本地服务由Context.startService()启动。启动以后,这些类型的服务将持续运行,直到客户端调用服务的 Context.stopService()或者服务自己调用 stopSelf()。请注意,当调用Context.startService()时,系统将实例化服务并调用服务的 onStart()方法。请记住,如果在服务启动之后(也就是服务运行时)调用 Context.startService()不会为服务创建另一个实例,但这样做将调用服务的 onStart()方法。下面给出了两个本地服务的实例。 
     一:定期在网络(比如Intent)上检索数据的服务 (用于上传或下载信息)。 
     二:任务执行程序服务,让应用程序的活动提交作业并对它们进行排队以供处理。 

下面这个例子是一一个本地服务的例子 这里例子是 我们在服务的不同状态,如服务创建、服务启动、服务停止等 定义一个消息 通过状态栏来提醒用户 后台服务的不同状态。 
  运行效果如下 

 

 

 

先来看看我们的Service类 
BackgroundService.java 

Java代码   收藏代码
  1. package xiaohang.zhimeng;  
  2.   
  3. import android.app.Notification;  
  4. import android.app.NotificationManager;  
  5. import android.app.PendingIntent;  
  6. import android.app.Service;  
  7. import android.content.Intent;  
  8. import android.os.IBinder;  
  9.   
  10. public class BackgroundService extends Service {  
  11.   
  12.     private NotificationManager notificationMgr;  
  13.   
  14.     @Override  
  15.     public void onCreate() {  
  16.         super.onCreate();  
  17.         notificationMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);  
  18.   
  19.         displayNotificationMessage("starting Background Service");  
  20.   
  21.         Thread thr = new Thread(nullnew ServiceWorker(), "BackgroundSercie");  
  22.         thr.start();  
  23.     }  
  24.   
  25.     @Override  
  26.     public IBinder onBind(Intent intent) {  
  27.         return null;  
  28.     }  
  29.   
  30.     class ServiceWorker implements Runnable {  
  31.         @Override  
  32.         public void run() {  
  33.             // do background processing here.....  
  34.             // stop the service when done...  
  35.             // BackgroundService.this.stopSelf()  
  36.         }  
  37.     }  
  38.   
  39.     @Override  
  40.     public void onDestroy() {  
  41.         displayNotificationMessage("stopping Background Service");  
  42.         super.onDestroy();  
  43.     }  
  44.   
  45.     @Override  
  46.     public void onStart(Intent intent, int startId) {  
  47.         super.onStart(intent, startId);  
  48.     }  
  49.   
  50.     private void displayNotificationMessage(String message) {  
  51.         Notification notification = new Notification(R.drawable.icon, message,  
  52.                 System.currentTimeMillis());  
  53.   
  54.         PendingIntent contentIntent = PendingIntent.getActivity(this0,  
  55.                 new Intent(this, Activity01.class), 0);  
  56.   
  57.         notification.setLatestEventInfo(this"Background Service", message,  
  58.                 contentIntent);  
  59.   
  60.         notificationMgr.notify(R.id.app_notification_id, notification);  
  61.     }  
  62. }  


Activity01类 
Java代码   收藏代码
  1. package xiaohang.zhimeng;  
  2. import android.app.Activity;  
  3. import android.content.Intent;  
  4. import android.os.Bundle;  
  5. import android.util.Log;  
  6. import android.view.View;  
  7. import android.view.View.OnClickListener;  
  8. import android.widget.Button;  
  9.   
  10. public class Activity01 extends Activity {  
  11.   
  12.     private static final String TAG = "Activity01";  
  13.   
  14.     @Override  
  15.     public void onCreate(Bundle savedInstanceState) {  
  16.         super.onCreate(savedInstanceState);  
  17.         setContentView(R.layout.main);  
  18.   
  19.         Log.d(TAG, "starting service");  
  20.   
  21.         Button bindBtn = (Button) findViewById(R.id.bindBtn);  
  22.         bindBtn.setOnClickListener(new OnClickListener() {  
  23.             @Override  
  24.             public void onClick(View v) {  
  25.                 startService(new Intent(Activity01.this,  
  26.                         BackgroundService.class));  
  27.             }  
  28.         });  
  29.   
  30.         Button unbindBtn = (Button) findViewById(R.id.unbindBtn);  
  31.         unbindBtn.setOnClickListener(new OnClickListener() {  
  32.             @Override  
  33.             public void onClick(View v) {  
  34.                 stopService(new Intent(Activity01.this, BackgroundService.class));  
  35.             }  
  36.         });  
  37.     }  
  38. }  


布局文件 
Xml代码   收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7. <TextView    
  8.     android:layout_width="fill_parent"   
  9.     android:layout_height="wrap_content"   
  10.     android:text="@string/hello"  
  11.     />  
  12. <Button  android:id="@+id/bindBtn"  
  13.     android:layout_width="wrap_content"  
  14.     android:layout_height="wrap_content"  
  15.     android:text="Bind"/>  
  16.   
  17.     <Button android:id="@+id/unbindBtn"  
  18.         android:layout_width="wrap_content"  
  19.         android:layout_height="wrap_content"  
  20.         android:text="UnBind"/>  
  21. </LinearLayout>  


我们需要创建一个图标 并将其放在项目的drawable文件夹内,我用的项目自带的那个。需要为通知管理器NotificationManager提供一个应用程序级唯一ID(整数)。要创建唯一ID,可以向字符串资源文件 /res/values/strings.xml 添加一个项ID。当调用notify()方法时,会将唯一ID 传递给通知管理器。 
Xml代码   收藏代码
  1. <item type=”id” name=”app_notification_id”/>  


最后,需要向 AndroidManifest.xml 文件添加
Xml代码   收藏代码
  1. <service android:name=”BackgroundService”/>  

标记,将其作为<application>的子标签。 

 

     BackgroundServie是承载服务的应用程序组件使用服务的一个典型例子。换言之,运行服务的应用程序也是服务的唯一使用者。因为该服务不支持其进程外的客户端,所以它是本地服务。由于本地服务不是远程服务,所以它在bind()方法中返回null。因此,绑定此服务的唯一 方法是调用Context.startService()。本地服务的重要方法包括 onCreate()、onStart()、stop()*和onDestroy()。 

     在BackgroundService的 onCreate()方法中,我们创建了一个线程来完成服务的主要工作。我们需要应用程序的主线程来处理用户界面,所以将服务的工作委派给一个辅助线程。另请注意,我们在onCreate()而不是onStart()中创建和启动线程。这样做是因为, onCreate()只会被调用一次,我们也希望在服务生命周期内只创建一次该线程。onStart()方法可以调用多次,所以它不符合此处的要求。我们在线程的run()方法实现中没有做任何事情,可以在这里执行HTTP调用、查询数据库等。 

     BackgroundService还使用NotificationManager类,以在服务启动和停止时向用户发送通知。这是本地服务将信息传递回用户的一种方式。要向用户发送通知,需要调用 getSystemService(NOTIFICATION_SERVICE)来获得通知管理器。来自通知管理器的消息将显示在状态栏中。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值