service(改)
16lz
2021-01-26
手机是人们生活中不可或缺的一个有用工具。我们在使用手机时,往往是多线程的,而且是会突然间断的。比如我们会一边浏览网页,一边听MP3。或者正在发短信的时候,突然打进来电话。这样我们必定会离开当前的用户界面。比如你会关闭MP3歌曲列表,去发短信,所以往往就需要有些程序在后台完成,暂时脱离屏幕。这时就可以用到Android中的Service
下面会用一个播放MP3的小应用来体会一下Android的Service
******************************
另外也可参照以下哥们的博客:
① http://wayfarer.iteye.com/blog/586167
******************************
1、什么是Service
Android引入了Service的概念是为了处理后台进程。Service不实现任何用户界面。最常见的例子如:媒体播放器程序,它可以在转到后台运行的时候仍然能保持播放歌曲;或者如文件下载程序,它可以在后台执行文件的下载。
它跟Activity的级别差不多,但是他不能自己运行,需要通过某一个Activity或者其他Context对象来调用, Context.startService() 和 Context.bindService()。
2、Service的生命周期
Service的生命周期方法比Activity少一些,只有onCreate, onStart, onDestroy
我们有两种方式启动一个Service,他们对Service生命周期的影响是不一样的。两种启动Service的方式有所不同。 这里要说明一下的是如果你在Service的onCreate或者onStart做一些很耗时间的事情,最好在Service里启动一个线程来完成,因为Service 是跑在主线程中,会影响到你的UI操作或者阻塞主线程中的其他事情。
3、创建一个Service
Android中已经定义了一个 ‘Service’类,所有其他的Service都继承于该类。Service类中定义了一系列的生命周期相关的方法,如: onCreate(), onStart(), onDestroy()
4、提高 Service 优先级
Android 系统对于内存管理有自己的一套方法,为了保障系统有序稳定的运行,系统内部会自动分配,控制程序的内存使用。当系统觉得当前的资源非常有限的时候,为了保证一些优先级高的程序能运行,就会杀掉一些他认为不重要的程序或者服务来释放内存。这样就能保证真正对用户有用的程序仍然再运行。如果你的 Service 碰上了这种情况,多半会先被杀掉。但如果你增加 Service 的优先级就能让他多留一会,我们可以用 setForeground(true) 来设置 Service 的优先级。
为什么是 foreground ? 默认启动的 Service 是被标记为 background,当前运行的 Activity 一般被标记为 foreground,也就是说你给 Service 设置了 foreground 那么他就和正在运行的 Activity 类似优先级得到了一定的提高。当让这并不能保证你得 Service 永远不被杀掉,只是提高了他的优先级。
5、启动Service
有了 Service 类我们如何启动他呢,有两种方法:
Context.startService()
context.startService() ->onCreate()- >onStart()->Service running
context.stopService() | ->onDestroy() ->Service stop
Context.bindService()
context.bindService()->onCreate()->onBind()->Service running
onUnbind() -> onDestroy() ->Service stop
在同一个应用任何地方调用 startService() 方法就能启动 Service 了,然后系统会回调 Service 类的 onCreate() 以及 onStart() 方法。这样启动的 Service 会一直运行在后台,直到 Context.stopService() 或者 selfStop() 方法被调用。如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行。该Service的调用者再启动起来后可以通过stopService关闭Service。
另外如果一个 Service 已经被启动,其他代码再试图调用 startService() 方法,是不会执行 onCreate() 的,但会重新执行一次 onStart() 。
另外一种 bindService() 方法的意思是,把这个 Service 和调用 Service 的客户类绑起来,如果调用这个客户类被销毁,Service 也会被销毁。用这个方法的一个好处是,bindService() 方法执行后 Service 会回调上边提到的 onBind() 方发,你可以从这里返回一个实现了 IBind 接口的类,在客户端操作这个类就能和这个服务通信了,比如得到 Service 运行的状态或其他操作。如果 Service 还没有运行,使用这个方法启动 Service 就会 onCreate() 方法而不会调用 onStart()。
用其他方式启动 Service
其实不光能从 Activity 中启动 Service ,还有一个很有用的方法是接收系统的广播,这就要用到 Receiver 。在 Mainfest 文件中配置你得 Receiver 能接收什么样的广播消息,那么即使你得程序没有显示给用户,你的 Service 也能启动。你要做的就是继承 android.content.BroadcastReceiver ,然后实现 onReceive(Context context, Intent intent) 方法,就可以启动你得 Service 了。这里不能 bindService 因为一个 Receiver 是一个短暂存在的对象,所以 bind 是没有什么意义的。
与 Service 通信并且让它持续运行
如果我们想保持和 Service 的通信,又不想让 Service 随着 Activity 退出而退出呢?
可以先 startService() 再 bindService()。当不需要绑定的时候再执行 unbindService() 方法,执行这个方法只会触发 Service 的 onUnbind() 而不会把这个 Service 销毁。这样就可以既保持和 Service 的通信,也不会随着 Activity 销毁而销毁了。
6、通过不同的方法启动service所带来的不同
① 通过startService
Service会经历 onCreate -> onStart, stopService的时候直接onDestroy。
如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行。
下次调用者再起来可以stopService。
② 通过bindService
Service只会运行onCreate,这个时候调用者和Service绑定在一起,调用者退出 了,Srevice就会调用onUnbind->onDestroyed,所谓绑定在一起就共存亡了。
③ 交织在一起调用
要是这几个方法交织在一起的话,会出现什么情况呢?
一个原则是Service的onCreate的方法只会被调用一次,就是你无论多少次的startService又 bindService,Service只被创建一次。
a.如果先是bind了,那么start的时候就直接运行Service的onStart方法。这时候如果调 用stop方法就关不掉service了,就是stopService不好使了,只能先UnbindService, 再StopService
b.如果先是start,那么bind的时候就直接运行onBind方法。所以是先start还是先bind行为是有区别的。
MP3TestActivity.java提供控制界面
MusicService.java提供MP3播放功能,在开启播放后,可以尝试退出应用程序界面。看是否音乐还在继续播放。
layout/mean.xml
AndroidManifest.xml
参考项目结构
================ 20110630 ====================
与远程Service通信(进程间Service通信):
如何两个进程间的Service需要进行通信,则需要把对象序列化后进行互相发送。
Android提供了一个 AIDL (Android接口定义语言)工具来处理序列化和通信。这种情况下Service需要以aidl文件的方式提供服务接口,AIDL工具将生成一个相应的java接口,并且在生成的服务接口中包含一个功能调用的stub服务桩类。Service的实现类需要去继承这个 stub服务桩类。Service的onBind方法会返回实现类的对象,之后你就可以使用它了,参见下例:
先创建一个IMyRemoteService.aidl文件,内容如下:
package com.wissen.testApp;
interface IMyRemoteService {
int getStatusCode();
}
如果你正在使用eclipse的 Android插件,则它会根据这个aidl文件生成一个Java接口类。生成的接口类中会有一个内部类Stub类,你要做的事就是去继承该Stub类:
package com.wissen.testApp;
class RemoteService implements Service {
int statusCode;
@Override
public IBinder onBind(Intent arg0) {
return myRemoteServiceStub;
}
private IMyRemoteService.Stub myRemoteServiceStub = new IMyRemoteService.Stub() {
public int getStatusCode() throws RemoteException {
return 0;
}
};
…
}
当客户端应用连接到这个Service时,onServiceConnected方法将被调用,客户端就可以获得IBinder对象。参看下面的客户端onServiceConnected方法:
…
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IMyRemoteService myRemoteService = IMyRemoteService.Stub.asInterface(service);
try {
statusCode = myRemoteService.getStatusCode();
} catch(RemoteException e) {
// handle exception
}
Log.i(”INFO”, “Service bound “);
}
…
};
权限:
我们可以在AndroidManifest.xml文件中使用<service>标签来指定Service访问的权限:
<service class=”.service.MyService” android:permission=”com.wissen.permission.MY_SERVICE_PERMISSION”>
<intent-filter>
<action android:value=”com.wissen.testApp.service.MY_SERVICE” />
</intent-filter>
</service>
之后应用程序要访问该Service的话就需要使用<user-permission>标签来指定相应的权限:
<uses-permission android:name=”com.wissen.permission.MY_SERVICE_PERMISSION”>
</uses-permission>
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xiangyong2008/archive/2010/04/26/5530427.aspx
下面会用一个播放MP3的小应用来体会一下Android的Service
******************************
另外也可参照以下哥们的博客:
① http://wayfarer.iteye.com/blog/586167
******************************
1、什么是Service
Android引入了Service的概念是为了处理后台进程。Service不实现任何用户界面。最常见的例子如:媒体播放器程序,它可以在转到后台运行的时候仍然能保持播放歌曲;或者如文件下载程序,它可以在后台执行文件的下载。
它跟Activity的级别差不多,但是他不能自己运行,需要通过某一个Activity或者其他Context对象来调用, Context.startService() 和 Context.bindService()。
2、Service的生命周期
Service的生命周期方法比Activity少一些,只有onCreate, onStart, onDestroy
我们有两种方式启动一个Service,他们对Service生命周期的影响是不一样的。两种启动Service的方式有所不同。 这里要说明一下的是如果你在Service的onCreate或者onStart做一些很耗时间的事情,最好在Service里启动一个线程来完成,因为Service 是跑在主线程中,会影响到你的UI操作或者阻塞主线程中的其他事情。
3、创建一个Service
Android中已经定义了一个 ‘Service’类,所有其他的Service都继承于该类。Service类中定义了一系列的生命周期相关的方法,如: onCreate(), onStart(), onDestroy()
4、提高 Service 优先级
Android 系统对于内存管理有自己的一套方法,为了保障系统有序稳定的运行,系统内部会自动分配,控制程序的内存使用。当系统觉得当前的资源非常有限的时候,为了保证一些优先级高的程序能运行,就会杀掉一些他认为不重要的程序或者服务来释放内存。这样就能保证真正对用户有用的程序仍然再运行。如果你的 Service 碰上了这种情况,多半会先被杀掉。但如果你增加 Service 的优先级就能让他多留一会,我们可以用 setForeground(true) 来设置 Service 的优先级。
为什么是 foreground ? 默认启动的 Service 是被标记为 background,当前运行的 Activity 一般被标记为 foreground,也就是说你给 Service 设置了 foreground 那么他就和正在运行的 Activity 类似优先级得到了一定的提高。当让这并不能保证你得 Service 永远不被杀掉,只是提高了他的优先级。
5、启动Service
有了 Service 类我们如何启动他呢,有两种方法:
Context.startService()
context.startService() ->onCreate()- >onStart()->Service running
context.stopService() | ->onDestroy() ->Service stop
Context.bindService()
context.bindService()->onCreate()->onBind()->Service running
onUnbind() -> onDestroy() ->Service stop
在同一个应用任何地方调用 startService() 方法就能启动 Service 了,然后系统会回调 Service 类的 onCreate() 以及 onStart() 方法。这样启动的 Service 会一直运行在后台,直到 Context.stopService() 或者 selfStop() 方法被调用。如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行。该Service的调用者再启动起来后可以通过stopService关闭Service。
另外如果一个 Service 已经被启动,其他代码再试图调用 startService() 方法,是不会执行 onCreate() 的,但会重新执行一次 onStart() 。
另外一种 bindService() 方法的意思是,把这个 Service 和调用 Service 的客户类绑起来,如果调用这个客户类被销毁,Service 也会被销毁。用这个方法的一个好处是,bindService() 方法执行后 Service 会回调上边提到的 onBind() 方发,你可以从这里返回一个实现了 IBind 接口的类,在客户端操作这个类就能和这个服务通信了,比如得到 Service 运行的状态或其他操作。如果 Service 还没有运行,使用这个方法启动 Service 就会 onCreate() 方法而不会调用 onStart()。
public class BindMusicService extends Service { 06 07 private static final String TAG = "MyService"; 08 private MediaPlayer mediaPlayer; 09 10 private final IBinder binder = new MyBinder(); 11 12 public class MyBinder extends Binder { 13 BindMusicService getService() { 14 return BindMusicService.this; 15 } 16 } 17 18 /* 19 * (non-Javadoc) 20 * 21 * @see android.app.Service#onBind(android.content.Intent) 22 */ 23 @Override 24 public IBinder onBind(Intent intent) { 25 Log.d(TAG, "onBind"); 26 play(); 27 return binder; 28 } 29 30 @Override 31 public void onCreate() { 32 super.onCreate(); 33 34 Log.d(TAG, "onCreate"); 35 Toast.makeText(this, "show media player", Toast.LENGTH_SHORT).show(); 36 37 38 } 39 40 @Override 41 public void onDestroy() { 42 super.onDestroy(); 43 44 Log.d(TAG, "onDestroy"); 45 Toast.makeText(this, "stop media player", Toast.LENGTH_SHORT); 46 if(mediaPlayer != null){ 47 mediaPlayer.stop(); 48 mediaPlayer.release(); 49 } 50 } 51 52 53 public void play() { 54 if (mediaPlayer == null) { 55 mediaPlayer = MediaPlayer.create(this, R.raw.tmp); 56 mediaPlayer.setLooping(false); 57 } 58 if (!mediaPlayer.isPlaying()) { 59 mediaPlayer.start(); 60 } 61 } 62 63 public void pause() { 64 if (mediaPlayer != null && mediaPlayer.isPlaying()) { 65 mediaPlayer.pause(); 66 } 67 } 68 69 public void stop() { 70 if (mediaPlayer != null) { 71 mediaPlayer.stop(); 72 try { 73 // 在调用stop后如果需要再次通过start进行播放,需要之前调用prepare函数 74 mediaPlayer.prepare(); 75 } catch (IOException ex) { 76 ex.printStackTrace(); 77 } 78 } 79 } 80 81 }
用其他方式启动 Service
其实不光能从 Activity 中启动 Service ,还有一个很有用的方法是接收系统的广播,这就要用到 Receiver 。在 Mainfest 文件中配置你得 Receiver 能接收什么样的广播消息,那么即使你得程序没有显示给用户,你的 Service 也能启动。你要做的就是继承 android.content.BroadcastReceiver ,然后实现 onReceive(Context context, Intent intent) 方法,就可以启动你得 Service 了。这里不能 bindService 因为一个 Receiver 是一个短暂存在的对象,所以 bind 是没有什么意义的。
与 Service 通信并且让它持续运行
如果我们想保持和 Service 的通信,又不想让 Service 随着 Activity 退出而退出呢?
可以先 startService() 再 bindService()。当不需要绑定的时候再执行 unbindService() 方法,执行这个方法只会触发 Service 的 onUnbind() 而不会把这个 Service 销毁。这样就可以既保持和 Service 的通信,也不会随着 Activity 销毁而销毁了。
6、通过不同的方法启动service所带来的不同
① 通过startService
Service会经历 onCreate -> onStart, stopService的时候直接onDestroy。
如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行。
下次调用者再起来可以stopService。
② 通过bindService
Service只会运行onCreate,这个时候调用者和Service绑定在一起,调用者退出 了,Srevice就会调用onUnbind->onDestroyed,所谓绑定在一起就共存亡了。
③ 交织在一起调用
要是这几个方法交织在一起的话,会出现什么情况呢?
一个原则是Service的onCreate的方法只会被调用一次,就是你无论多少次的startService又 bindService,Service只被创建一次。
a.如果先是bind了,那么start的时候就直接运行Service的onStart方法。这时候如果调 用stop方法就关不掉service了,就是stopService不好使了,只能先UnbindService, 再StopService
b.如果先是start,那么bind的时候就直接运行onBind方法。所以是先start还是先bind行为是有区别的。
MP3TestActivity.java提供控制界面
package com.android.mp3test;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;public class MP3TestActivity extends Activity {private Button start;private Button stop;private Intent i;/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);start = (Button) this.findViewById(R.id.start);stop = (Button) this.findViewById(R.id.stop);// 指向MP3播放Service的actioni = new Intent("com.kennan.android.music");start.setOnClickListener(startListener);stop.setOnClickListener(stopListener);}private OnClickListener startListener = new OnClickListener() {public void onClick(View v) {// 开始服务MP3TestActivity.this.startService(i);}};private OnClickListener stopListener = new OnClickListener() {public void onClick(View v) {// 结束服务MP3TestActivity.this.stopService(i);}};}
MusicService.java提供MP3播放功能,在开启播放后,可以尝试退出应用程序界面。看是否音乐还在继续播放。
package com.android.mp3test;import android.app.Service;import android.content.Intent;import android.media.MediaPlayer;import android.os.IBinder;public class MusicService extends Service {private MediaPlayer player;public IBinder onBind(Intent arg0) {return null;}public void onStart(Intent intent, int startId) {super.onStart(intent, startId);// 在服务开始时,启动MP3播放player = MediaPlayer.create(this, R.raw.music);player.start();}public void onDestroy() {// 在服务消灭时,关闭MP3播放player.stop();super.onDestroy();}}
layout/mean.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" ><TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <Button android:id="@+id/start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/start" /> <Button android:id="@+id/stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/stop" /> </LinearLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.android.mp3test" android:versionCode="1"android:versionName="1.0"><application android:icon="@drawable/icon" android:label="@string/app_name"><activity android:name=".MP3TestActivity" android:label="@string/app_name"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><service android:name="MusicService"><intent-filter><action android:name="com.kennan.android.music" /><category android:name="android.intent.category.DEFAULT" /></intent-filter></service></application><uses-sdk android:minSdkVersion="4" /></manifest>
参考项目结构
================ 20110630 ====================
与远程Service通信(进程间Service通信):
如何两个进程间的Service需要进行通信,则需要把对象序列化后进行互相发送。
Android提供了一个 AIDL (Android接口定义语言)工具来处理序列化和通信。这种情况下Service需要以aidl文件的方式提供服务接口,AIDL工具将生成一个相应的java接口,并且在生成的服务接口中包含一个功能调用的stub服务桩类。Service的实现类需要去继承这个 stub服务桩类。Service的onBind方法会返回实现类的对象,之后你就可以使用它了,参见下例:
先创建一个IMyRemoteService.aidl文件,内容如下:
package com.wissen.testApp;
interface IMyRemoteService {
int getStatusCode();
}
如果你正在使用eclipse的 Android插件,则它会根据这个aidl文件生成一个Java接口类。生成的接口类中会有一个内部类Stub类,你要做的事就是去继承该Stub类:
package com.wissen.testApp;
class RemoteService implements Service {
int statusCode;
@Override
public IBinder onBind(Intent arg0) {
return myRemoteServiceStub;
}
private IMyRemoteService.Stub myRemoteServiceStub = new IMyRemoteService.Stub() {
public int getStatusCode() throws RemoteException {
return 0;
}
};
…
}
当客户端应用连接到这个Service时,onServiceConnected方法将被调用,客户端就可以获得IBinder对象。参看下面的客户端onServiceConnected方法:
…
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IMyRemoteService myRemoteService = IMyRemoteService.Stub.asInterface(service);
try {
statusCode = myRemoteService.getStatusCode();
} catch(RemoteException e) {
// handle exception
}
Log.i(”INFO”, “Service bound “);
}
…
};
权限:
我们可以在AndroidManifest.xml文件中使用<service>标签来指定Service访问的权限:
<service class=”.service.MyService” android:permission=”com.wissen.permission.MY_SERVICE_PERMISSION”>
<intent-filter>
<action android:value=”com.wissen.testApp.service.MY_SERVICE” />
</intent-filter>
</service>
之后应用程序要访问该Service的话就需要使用<user-permission>标签来指定相应的权限:
<uses-permission android:name=”com.wissen.permission.MY_SERVICE_PERMISSION”>
</uses-permission>
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xiangyong2008/archive/2010/04/26/5530427.aspx
更多相关文章
- 基于 Android(安卓)NDK 的学习之旅-----Java 调用C(附源码)
- Android内核开发:系统启动速度优化
- 深入剖析Android消息机制原理
- Unity调用Android(安卓)jar包方法——(三、使用UnitySendMessage
- [Android] [Android的视窗系统及显示机制][下] [底层显示子系统S
- 『叫兽学堂』手把手教你如何正确启动Android(安卓)SDK 1.5模拟器
- Android模拟器正确应用与安装方法
- Android运用自定义控件实现闪烁字
- Android(安卓)4.4、5.1、6.0 屏蔽Home键