上篇文章中我们讲到了SQL Server在建立连接时的加密。今天我们继续讨论SQL Server在建立完连接后在该连接上的数据传送加密。 默认情况下SQL Server是否加密收发的数据包答案是否定的。SQL Server默认只在建立连接时进行加密以保护客户端发送过来的账户登录信
请尊重他人劳动成果,请勿随意剽窃,转载请注明,谢谢!转载请注明出处:http://blog.csdn.net/evan_man/article/details/51800263
启动方式
启动Local Service(Client跟Service在同一个进程)
这类服务有个特点,就是它主要用于为某一个客户(Activity)提供单独的后台服务;
Context.startService()启动
如果调用该方法时对应Service还没有创建出来,则会调用onCreate方法;即Service只会创建一个实例; 调用多少次该方法就对应调用多少次Service端的onStartCommand方法;
Context.stopService()结束
无论之前调用了多少次startService,只需要调用一次该方法
启动Remote Service(Client跟Service不在同一个进程)
这类服务有个特点,就是它会定义一些接口并把接口暴露出来,以便其他应用进行操作;
多个客户端可以绑定同一个服务;
Context.bindService()方法建立连接,并启动
如果调用该方法时对应Service还没有创建出来,则会调用onCreate方法;即Service只会创建一个实例; Context如果之前没有和该Service绑定过,即执行bindService方法,那么就会执行Service的bindService方法;如果绑定过了就不会执行onBind方法
Context.unbindService()关闭连接
注意:
上面只是默认一种约定行为;如果是Remote Service建议使用bindService,因为bindService可以获取 Remote Service提供的接口;如果是Local Service建议使用sartService,因为startService很简单;
生命周期
Part1(纯粹的Start)
启动:startService方法启动 终止:调用stopService,或自身的stopSelf方法,系统资源不足android系统结束服务;(执行Service的onDestroy方法)
Part2(纯粹的Bind)
启动:bindService方法启动 终止:调用unbindService断开连接,之前调用bindService 的 Context 不存在了(如Activity被finish的时候);(执行Service的unBind和onDestroy方法)
Part3(混合的Start&Bind)
启动:如先startService,后bindService 终止:(调用stopService 或者 调用stopSelf)并且(不再有绑定的连接)==》onDestroy方法将会被调用;
注意:
Activity旋转的时候,意味着Activity重建了;旋转之前的使用 bindService 建立的连接便会断开(Context 不存在了); 使用了startService启动Service就需要调用stopService关闭服务;使用了bindService启动Service就需要调用unbindService关闭服务;它们都是成对出现的!!! 这里对bindService启动的Service会和启动它的Context共生死,这一点进行一下说明;如果ActivityA进行了bindService,ActivityB也bindService,那么当ActivityA进行了unbindService时,Service并不会调用onDestroy,因为它还有个bind没有解除(即跟ActivityB之间的bind)~;但是activityA跳转到ActivityB,有可能导致activityA被系统销毁,这样即使activityA代码中没有调用unbind,系统也会自动将activityA和service解绑,进而可能service就onDestroy了;当Activity2在bind的时候该service已经不存在了,最终还是要去创建一个service实例;为了避免上述问题这里建议,通过startService启动service,随后bindService进行activity和service的绑定,这样即使activity内容被销毁了,service还是不会调用onDestroy方法!
实现原理
Local Service:(Client和Service在同一个进程中)
Service端:
编写类继承android.app.Service类;实现onCreate、onbind、onStartCommand、onDestroy等方法 在Manifest.xml文件中注册该Service:如下
Client端:
bindService方式启动(关闭调用对应的unbindService())
bindService(new Intent(ServiceDemo.ACTION).setPackage(getPackageName()) , conn, BIND_AUTO_CREATE); 参数1说明:ServiceDemo.ACTION=="com.demo.SERVICE_DEMO";即上面Service在Manifest的定义的Action!public Intent (String action);Android5.0不支持隐式调用,需要指定packegename,如上面的方式,packegename指明了在哪个包中找和Action对应的组件,如果不指名package那么则在当前系统全局搜索,每个app对应一个package,定义在Manifest标签里面,此package并非指我们想要启动服务类所在的包名;
或者用Intent intent = new Intent(); intent.setClass(this,MyLocalService.class);的方式启动服务;之前我们经常用这个方式,而不是用Action;其实这部分是Intent的内容,可以去研究一下intent的使用方法和构造器!
参数3说明:BIND_AUTO_CREATE,即当服务不存在时,自动创建,如果服务已经启动了或者创建了,那么只会掉调用onBind方法 参数2说明:conn是一个实现了ServiceConnection接口的对象;实现了下面两个方法
onServiceConnected(ComponentName name, IBinder service)
客户端调用bindService;Service端对应调用onBind方法;如果onBind方法返回值不为null则执行 这里的onServiceConnected方法!(就是该方法的第二个参数,就是onBind方法的返回值);无论这里是不是执行onServiceConnected方法,都已经完成了客户端和Service的绑定,最后还是需要调用unBindService进行解绑; 通过该方法的第二个参数service可以获得Service提供的接口!!如: MyService.SimpleBinder sBinder = (MyService.SimpleBinder)service; //SimpleBinder是MyService的内部类,继承了Binder类 ,定义了add方法; sBinder.add(3, 5);
onServiceDisconnected(ComponentName name)
startService方式启动(关闭调用对应的stopService())
startService(new Intent(ServiceDemo.ACTION)).setPackage(getPackageName());
Remote Service:(Client和Service不在同一个进程中)(进程间通信毫无疑问使用了Binder)
Service端:
编写一个服务接口,不需要继承任何接口(假设该接口名为: ITestRemoteService);定义该服务会提供的服务(如一个add方法);以aidl格式保存!!
android会自动将该文件转换为java文件,并添加一些必要的内容,使其能够进行IPC(我们需要做的就是写aidl文件,随后编译一下工程即可!) IPC即进程间通信,底层通过Binder技术实现
编写类继承android.app.Service类;
有一个如下的Field:private ITestRemoteService.Stub stub= new ITestRemoteService.Stub(){ ..//实现了上面定义的如add方法 }
上面的ITestRemoteService是android对aidl文件转换为java文件后得到的java类,类中自动生成了一个Stub内部类 ;
在实现的onbind方法中返回上面生成的stub; 实现onCreate、onStartCommand、onDestroy等方法
在Manifest.xml文件中注册该Service
Client端:
bindService方式启动(关闭调用对应的unbindService())
bindService(intent, conn,Context.BIND_AUTO_CREATE); 参数1说明:Intent intent = new Intent("com.yq.RemoteService").setPackage(getPackageName());//packegename指明了在哪个包中找和Action对应的组件,如果不指名package那么则在当前系统全局搜索,每个app对应一个package,定义在Manifest标签里面,此package并非指我们想要启动服务类所在的包名; 参数2说明:BIND_AUTO_CREATE,即当服务不存在时,自动创建,如果服务已经启动了或者创建了,那么只会调用onBind方法 参数3说明:conn是一个实现了ServiceConnection接口的对象;实现了下面两个方法
onServiceConnected(ComponentName name, IBinder service)
客户端调用bindService;Service端对应调用onBind方法;如果onBind方法返回值不为null则执行 这里的onServiceConnected方法!(就是该方法的第二个参数,就是onBind方法的返回值);无论这里是不是执行onServiceConnected方法,都已经完成了客户端和Service的绑定,最后还是需要调用unBindService进行解绑; 通过该方法的第二个参数service可以获得Service提供的接口!!如: ITestRemoteService remoteService = ITestRemoteService.Stub.asInterface(service); ITestRemoteService就是我们定义了的接口,里面定义了add方法; 之后我们的Client就获得了这个Service,就可以任意时间访问对应的服务了~~
onServiceDisconnected(ComponentName name)
startService方式启动(关闭调用对应的stopService())
startService(intent); 参数说明:Intent intent = new Intent(); intent.setClassName("com.demo","com.demo.SERVICE_DEMO"); 可以发现如果通过startService启动服务那么就客户端没有任何返回可以收到!只能单向的向Service发送一个信号;
’
相关概念的区分(易模糊点)
StartService和bindService启动方法使用场景:
如果你只是想要 启动一个后台服务长期进行某项任务那么使用
startService 便可以 了;证明startService启动服务,你的期望不要太高;因为它不给客户端任何反馈;你可以通过broadcast来向客户端传数据,然而BroadcastReceiver 本身执行代码的时间是很短的!!因此不能对该方法期望过高!!总之startService很弱很弱的 ; 想要与正在运行的 Service 取得联系,推荐我们的终极武器bindService!!bindService很好很强大 ;
AndroidManifest.xml 里 Service 元素的常见选项
android:name,服务类名 android:label,服务的名字,如果此项不设置,那么默认显示的服务名则为类名 android:process,表示该服务是否运行在另外一个进程,如果设置了此项,那么将会在包名后面加上这段字符串表示另一进程的名字 android:enabled,如果此项设置为 true,那么 Service 将会默认被系统启动,不设置默认此项为 false android:exported,表示该服务是否能够被其他应用程序所控制或连接,不设置默认此项为 false android:icon,服务的图标
Service&Thread
Thread:Thread 是程序执行的最小单元,它是分配CPU的基本单位。可以用 Thread 来执行一些异步的操作。 Service 是android的一种机制,当它运行的时候如果是Local Service,那么对应的 Service 是运行在主进程的 main 线程上的(运行耗时操作会导致ANR) ;如果是Remote Service,那么对应的 Service 则是运行在独立进程的 main 线程上; 用Service而不用Thread的好处就是我们可以随时通过BindService或者startService跟Service进行通信,换成Thread一旦start我们将无能为力了~;Service很乖,Thread很野; Service的职责是负责后台的耗时的工作; Android的后台就是指,它的运行是完全不依赖UI的,即使Activity被销毁,或者程序被关闭,只要进程还在,Service就可以继续运行;所以在Service中创建Thread比在Acitivity中创建线程的好处在于,Service在一个应用中是稳定存在的,而Activity朝不保夕(应用中经常有各种Activity之间的跳转操作),一旦它销毁了,那么它所创建的线程,将处于游离状态,不受控制,Service不会出现这样的问题;
一个比较好的Service往往是如下的样子:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
// 开始执行后台任务
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
class MyBinder extends Binder {
public void startDownload() {
new Thread(new Runnable() {
@Override
public void run() {
// 执行具体的下载任务
}
}).start();
}
}
前台Service和后台Service的区别于实现
后台Service存在被回收的隐患
我们启动的Service一般都是后台运行的Service;因为Service的系统优先级还是比较低的,当系统出现内存不足情况时,就有可能会回收掉正在后台运行的Service;
前台Service避免被回收的隐患
前台Service和普通Service最大的区别就在于,它会一直有一个正在运行的图标在系统的状态栏显示,下拉状态栏后可以看到更加详细的信息,非常类似于通知的效果;这让人想到,小米一个rom开发工程师控诉qq虽然进入了后台,但是在屏幕中展示一个像素点,使得该应用永远处于前台,所以Service永远不会被清除掉!!
创建一个前台Service(以下操作都是在Service里面进行的)
创建一个Notification
CharSequence text = getText(R.string.remote_service_started);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, Controller.class), 0); //指定点击该Notification的时候,应该跳转到的Activity
Notification notification = new Notification.Builder(this)
.setSmallIcon(R.drawable.stat_sample) // the status icon
.setTicker(text) // the status text
.setWhen(System.currentTimeMillis()) // the time stamp
.setContentTitle(getText(R.string.local_service_label)) // the label of the entry
.setContentText(text) // the contents of the entry
.setContentIntent(contentIntent) // The intent to send when the entry is clicked
.build();
让Service变成一个前台Service,并会将通知显示出来
startForeground( R.string.remote_service_started, notification); //等价于NotificationManager.notify(int, Notification)
让Service变成一个后台Service,并会将通知从通知栏撤销
stopForeground( true); //该动作不会使得Service被destroy但是将Service转为后台应用
远程Service和本地Service的优劣比较
ANR问题
ANR问题,本地Service会运行本进程的主线程即UI线程中,因此运行耗时程序,触发ANR;如果是远程Service则阻塞的是另外一个进程的主线程,对当前进程无影响,因此不会触发ANR;
远程Service比本地Service要好?
其实远程Service实现起来比本地Service要复杂一点,大体流程如下,具体实现代码参考:
本地service:
写一个继承Service类的子类 xml文件注册该Serive 客户端startService、bindServcie;传入的intent为(this. MyService.class)的形式
远程Service:
写一个aidl 文件(RemoteServce.aidl),内容就是定义的一个普通java接口的代码;随后编译得到一个对应同名的java文件(RemoteService.java) 写一个实现了RemoteService.Stub接口 的类(RemoteServiceImp) 写一个继承Service类的子类,该类中有一个RemoteServiceImp的对象,并在onBind方法中返回该对象 xml注册上面的service:注意添加标签android:process = ":remote" <intent-flter> <action>android:name = "com.evan.MyService"</action> </Intent-filter> 客户端startService、bindServcie;传入的intent为(this. "com.evan.MyService" )的形式 ServiceConnection中得到的IBinder对象,转换RemoteServiceImp remoteService = RemoteService.Stub.AsInterface (ibinder);
Client和Service之间通信方式的概述:
通过startAcitvity启动Service,可以传输一个Intent过去;这是单向的传输,适用于命令模式; 通过bindActivity启动Service,可以利用ServiceConnection接口,回调得到Iservice对象(注意这里的Iservice是我们定义的一个接口),通过该对象我们可以获取到所有Service向外界提供的服务;
用法一:(Android关于Serive给的例子中有这个案例)
获得来自Service的一个android.os.Messenger对象;该Messenger跟Handler使用方法类似,其实Messenger的某一个构造器参数就可以是一个Handler对象; 这样我们就可以利用该Messenger向Remote Service发送信息了; Client也可以创建一个Messenger,将该Messenger注册到Remote Service那边,这样Service就可以通过这个Messenger向Client发送数据了;上面就实现了双向通行 注意:服务端Messager就是通过Handler来构建的;利用mMessenger.getBinder()返回IBinder对象;客户单使用IBinder对象构造出Messager对象;而且Messager实现了Parcel接口!!意味着可以利用Binder在进程间进行传递了。
用法二:利用获得的Iservice对象,调用其中的服务接口,获取相关数据,或者发送某种命令;
跟StartActivity的区别:可以得到服务的返回值,因为是实实在在的调用了Service的一个方法; 跟StartActivity相同的地方:Client占据了主动权;
顶
0
踩
0