android Service学习笔记

服务简介

Service在继承关系上是Activity的大爷,也就是说Activity多继承了一个类,封装了界面相关,等等其他操作。

服务没有onPause、onStop、onResume、onRestart方法,因为service没有界面,长期运行在后台。

startService方式启动服务

Start方式启动服务声明周期:

服务被创建时依次调用onCreate、onStartCommand;

同一个服务只能被创建一次(onCreate),再次创建就只会执行onStartCommand;

一个服务只能被停止一次;

生命周期的方法:

onCreate:服务被创建的时候调用这个方法;

onStartCommand :开启服务

onDestroy:销毁服务

Start方式服务的创建步骤

1. 自定义服务类继承Service,并实现相关函数

2. 在配置文件中声明服务

3. 启动服务(startService,后面讲解bindService)

bindService方式启动服务

bind方式开启服务的生命周期

bindService绑定服务、unBindService解除绑定的服务;

服务是在被绑定的时候被创建,调用oncreate、onbind方法;

服务只能被绑定一次;

服务只能被解除绑定一次,解除绑定的时候调用onUnbind、onDestrory方法,如果多次解除绑定会抛出异常;

推荐的方式:

startService:开启并创建一个服务,服务长期运行在后台;

bindService:绑定服务,可以调用服务里面的方法;

unBindService:解除服务,停止服务里面的方法;

stopService:停止服务,销毁服务对象;

为什么要引入bindservice的API

1.服务启动后有时候会需要调用服务里面的方法,这就需要bindService来绑定服务

2.为了调用服务中的业务逻辑方法。

绑定服务调用服务方法的过程

通过bindservice方式实现调用服务里面业务逻辑方法:

步骤:

1、在服务类中创建一个中间人MyBinder类,继承了Binder,Binder实现了IBinder接口:

    	public class MyBinder extends Binder{
		}

2、在服务类里面创建了一个MyBinder的成员变量:

private MyBinder myBinder;

3、在MyBinder类中写一个方法用于调用服务的业务逻辑方法:

		public class MyBinder extends Binder{
		//使用中间人调用服务里的方法
		public void callMethodInService(){
			methodInService();
			}

		}

4、在activity中bindService时,定义了ServiceConnection,用它来监听绑定完成时的函数回调,在这个连接中实现了两个函数:

		private class MyConn implements ServiceConnection {
			/**
			 * 服务连接成功时调用这个方法
			 */
			@Override
			public void onServiceConnected(ComponentName name, IBinder service) {
				//得到服务绑定成功后返回的中间人MyBinder对象
				myBinder = (MyBinder) service;

			}

			/**
			 * 服务断开成功时调用这个方法
			 */
			@Override
			public void onServiceDisconnected(ComponentName name) {
				System.out.println("-------onServiceDisconnected-------");

			}

		}

5、通过在activity中通过中间人条用服务的业务逻辑方法:

myBinder.callMethodInService();

绑定服务抽取接口

接口(interface): 对外开放暴露的功能,但是不会暴露功能实现的细节;

让中间人实现服务接口的目的:只对外暴露接口里面业务逻辑方法,隐藏中间人里面的其他方法;

我们上面定义的MyBinder类太开放,如果别人获取了我们的MyBinder类的对象,就可以查看MyBinder类中的所有方法,

这是我们不允许的,我们只想别人看到我们允许别人调用的方法,而不想别人看到MyBinder类中的其他方法。要想实现这个

要求,我们让MyBinder再实现一个接口,接口中只有我们想让别人看到的方法,然后把接口给别人。

步骤:

1、创建一个服务的接口类,里面包含需要对外暴露的业务逻辑方法:

	public interface IService {
		public void callMethodInService();
	}

2、让服务中的中间人实现了服务的接口类:

		private class MyBinder extends Binder implements IService{

		//(实现服务接口中的方法)使用中间人调用服务里的方法
		public void callMethodInService(){
			methodInService();
		   }
		}

3、在activity中声明接口的成员变量:

private IService myBinder;

4、强制转换成服务的接口类型

	private class MyConn implements ServiceConnection {

		/**
		 * 服务连接成功时调用这个方法
		 */
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			//强制转换成服务的接口类型
			myBinder = (IService) service;
		}

5、在activity中通过接口的成员变量调用服务的业务逻辑方法:

public void call(View view){
		myBinder.callMethodInService();
	}

绑定服务的应用场景

1、需要在后台运行一定的业务逻辑,而且需要与服务器端交互数据,都是写在服务里面的。

2、天气预报、股票行情软件;

尤其是音乐播放器的播放暂停等,我们希望退出Activity后音乐可以继续播放,这就用到了Service,它可以在后台运行,我们又想在Activity中控制

音乐的播放暂停等功能,这就用到了BindService来调用服务里面的方法。

服务案例

电话窃听器(start方式启动服务)

步骤:

1、在工程中添加一个服务Service,重新onCreate方法;

2、在清单文件中配置服务;

3、在activity中开启服务;

4、在onCreate方法中使用TelephonyManager监听电话的状态;

5、在清单配置文件中添加权限

示例代码:

1、在工程中添加一个服务Service,重新onCreate方法:

  public class DHQTService extends Service {
				/**
			 * 当服务被创建的时候调用这个方法
			 */
			@Override
			public void onCreate() {
				System.out.println("=========onCreate=========");
				super.onCreate();

				TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);

				tm.listen(new MyListener(), PhoneStateListener.LISTEN_CALL_STATE);

			}
			}

2、在清单文件中配置服务:

			<service android:name="com.itheima.dhqtq.DHQTService"></service>

3、在activity中开启服务:

service = new Intent(this,DHQTService.class);
			//开启服务
			startService(service);	

4、在onCreate方法中使用TelephonyManager监听电话的状态:

			/**
			 * 当服务被创建的时候调用这个方法
			 */
			@Override
			public void onCreate() {
				System.out.println("=========onCreate=========");
				super.onCreate();
		<span style="white-space:pre">		</span>//通过获取系统服务得到TelephonyManager,用它来监听电话状态
				TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
		<span style="white-space:pre">		</span>//使用TelephonyManager监听电话状态,并设置监听器
				tm.listen(new MyListener(), PhoneStateListener.LISTEN_CALL_STATE);

			}

			/**
			*自定义一个电话状态监听器,监听电话
			*/
			private class mylistener extends phonestatelistener {
	<span style="white-space:pre">		</span>//使用MediaRecorder类录音
			private MediaRecorder r;
	<span style="white-space:pre">		</span>//电话状态改变会调用此函数
			@Override
			public void onCallStateChanged(int state, String incomingNumber) {

				try {
					// super.onCallStateChanged(state, incomingNumber);
					System.out.println("====state===============" + state);
					switch (state) {
					case TelephonyManager.CALL_STATE_IDLE:// 闲置状态
						System.out.println("关闭录音机,上传音频文件..................");
						if(r != null){
							r.stop();//录制完成
							r.release();//释放资源
							r = null;
							//上传文件
						}
						break;

					case TelephonyManager.CALL_STATE_RINGING:// 来电话状态
						System.out.println("准备好录音机,准备录音..................");
	<span style="white-space:pre">					</span>//创建一个MediaRecorder对象
						r = new MediaRecorder();
	<span style="white-space:pre">					</span>//设置捕获设备为麦克
						r.setAudioSource(MediaRecorder.AudioSource.MIC);
						r.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);//设置输出格式为3gp
						//设置输出目录
						//r.setOutputFile("/mnt/sdcard/info.3gp");
						r.setOutputFile(Environment.getExternalStorageDirectory()+"/info.3gp");
						r.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);//设置音频编码格式
						r.prepare(); //准备录制

						break;

					case TelephonyManager.CALL_STATE_OFFHOOK:// 接听状态
						System.out.println("开始录音..................");
						r.start();//开始录制
						break;

					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

		}

5、在清单配置文件中添加权限:

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
   		<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    	<uses-permission android:name="android.permission.RECORD_AUDIO"/>
    	<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

利用服务注册广播接收者

操作频繁的广播事件,如果只是在清单配置文件配置,是不生效的。需要使用代码注册才能生效;比如 屏幕解锁开锁,

电池电量低了,只能通过代码的方式进行注册才会生效。但是如果在Activity中动态注册广播,在Activity销毁时如果没有解除注册广播,Activity会提示

一个错误(Activity漏气(直译)了),所以在Activity销毁时需要解除注册广播,但解除我们就无法收到广播了,

如果你想一直接收操作频繁的广播事件,那就在服务中动态注册广播,而不去解除注册广播。

步骤:

动态注册广播接收者

// 1、得到广播接收者的对象
		ScreenBroadCastReceiver screenReceiver = new ScreenBroadCastReceiver();
		// 2、创建一个intentFilter对象
		IntentFilter filter = new IntentFilter();
		// 3、注册接收的事件类型
		filter.addAction("android.intent.action.SCREEN_ON");
		filter.addAction("android.intent.action.SCREEN_OFF");
		// 4、注册广播接收者
		this.registerReceiver(screenReceiver, filter);

远程服务aidl的写法

service的2个概念

本地服务  --    运行在当前自己应用的service

远程服务  ---   运行在其他应用进程里的service

调用远程服务

aidl--- Android interface definition language  出现目的是为了解决进程间通信

IPC---inner process communication

aidl调用远程服务的步骤

//首先开启远程服务支持

1.把src目录中的接口定义文件Iservice.java的后缀名改为aidl,要把public关键字去掉,保存后自动在gen目录下生成iservice.java文件

iservice.java中自动生成了Stub类

2.定义的中间人对象MyBinder 继承Stub

private class Mybinder extends Stub{.....}

//调用远程服务,把远程服务中的aidl文件拷贝过来

3. 要保证2个应用是统一aidl文件  aidl所在保证包名一样

4. 在获取中间人对象的时候直接用Stub类获取即可

iservice = Stub.asInterface(service);

远程服务的应用场景

1. 支付宝

2. 捕鱼达人  花钱买超级大炮   欢乐斗地主,

时间: 2024-08-02 10:57:35

android Service学习笔记的相关文章

Android Animation学习笔记

关于动画的实现,Android提供了Animation,在Android SDK介绍了2种Animation模式: 1. Tween Animation:通过对场景里的对象不断做图像变换(平移.缩放.旋转)产生动画效果,即是一种渐变动画: 2. Frame Animation:顺序播放事先做好的图像,是一种画面转换动画. 动画类型 下面先来看看Android提供的动画类型.Android的animation由四种类型组成 在XML文件中: alpha        渐变透明度动画效果 scale

java/android 设计模式学习笔记(7)---装饰者模式

这篇将会介绍装饰者模式(Decorator Pattern),装饰者模式也称为包装模式(Wrapper Pattern),结构型模式之一,其使用一种对客户端透明的方式来动态的扩展对象的功能,同时它也是继承关系的一种替代方案之一,但比继承更加灵活.在现实生活中也可以看到很多装饰者模式的例子,或者可以大胆的说装饰者模式无处不在,就拿一件东西来说,可以给它披上无数层不一样的外壳,但是这件东西还是这件东西,外壳不过是用来扩展这个东西的功能而已,这就是装饰者模式,装饰者的这个角色也许各不相同但是被装饰的对

android 开发学习笔记 (一)

每个app 都有一个自己的 linux 进程: 每个进程都在自己的虚拟机里执行 两个app 可以跑在一个进程,一个vm里 android app 四大组件:activity,content provider,      services, broardcast receivers Content Resolver 激活 Content Provider You can start an      activity (or give it something new to do) by passi

java/android 设计模式学习笔记(9)---代理模式

这篇博客我们来介绍一下代理模式(Proxy Pattern),代理模式也成为委托模式,是一个非常重要的设计模式,不少设计模式也都会有代理模式的影子.代理在我们日常生活中也很常见,比如上网时连接的代理服务器地址,更比如我们平时租房子,将找房子的过程代理给中介等等,都是代理模式在日常生活中的使用例子. 代理模式中的代理对象能够连接任何事物:一个网络连接,一个占用很多内存的大对象,一个文件,或者是一些复制起来代价很高甚至根本不可能复制的一些资源.总之,代理是一个由客户端调用去访问幕后真正服务的包装对象

疯狂Android讲义 - 学习笔记(八)

第10章 Service与BroadcastReceiver 10.1 Service简介 Service组件也是可执行的程序,有自己的生命周期,创建.配置Service与创建.配置Activity的过程基本相似.Service一直在后台运行,没有用户界面. 10.1.1 创建.配置Service 需要2个步骤:1 定义基础Service的子类,2 在AndroidManifest.xml文件中配置Service. Service与Activity都是从Context派生出来的,因此都可以调用C

疯狂Android讲义 - 学习笔记(五)

第五章 Android使用统一的Intent对象来封装“启动意图”,不管是启动Activity.Service组件.或者BroadcastReceiver等,提供了一致的编程模型.Intent设计有点类似于Struts2框架中的逻辑视图设计. Intent还是应用程序组件之间通信的重要媒介:数据封装成Bundle对象,Intent携带Bundle对象. 5.1 Intent对象详解 5.2 Intent的属性及intent-filter配置 5.2.1 Component属性 5.2.2 Act

java/android 设计模式学习笔记(14)---外观模式

这篇博客来介绍外观模式(Facade Pattern),外观模式也称为门面模式,它在开发过程中运用频率非常高,尤其是第三方 SDK 基本很大概率都会使用外观模式.通过一个外观类使得整个子系统只有一个统一的高层的接口,这样能够降低用户的使用成本,也对用户屏蔽了很多实现细节.当然,在我们的开发过程中,外观模式也是我们封装 API 的常用手段,例如网络模块.ImageLoader 模块等.其实我们在开发过程中可能已经使用过很多次外观模式,只是没有从理论层面去了解它. 转载请注明出处:http://bl

java/android 设计模式学习笔记(10)---建造者模式

这篇博客我们来介绍一下建造者模式(Builder Pattern),建造者模式又被称为生成器模式,是创造性模式之一,与工厂方法模式和抽象工厂模式不同,后两者的目的是为了实现多态性,而 Builder 模式的目的则是为了将对象的构建与展示分离.Builder 模式是一步一步创建一个复杂对象的创建型模式,它允许用户在不知道内部构建细节的情况下,可以更精细地控制对象的构造流程.一个复杂的对象有大量的组成部分,比如汽车它有车轮.方向盘.发动机.以及各种各样的小零件,要将这些部件装配成一辆汽车,这个装配过

java/android 设计模式学习笔记(一)---单例模式

前段时间公司一些同事在讨论单例模式(我是最渣的一个,都插不上嘴 T__T ),这个模式使用的频率很高,也可能是很多人最熟悉的设计模式,当然单例模式也算是最简单的设计模式之一吧,简单归简单,但是在实际使用的时候也会有一些坑. PS:对技术感兴趣的同鞋加群544645972一起交流 设计模式总目录 java/android 设计模式学习笔记目录 特点 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 单例模式的使用很广泛,比如:线程池(threadpool).缓存(cache).对